J'ai découvert que Ninject a récemment introduit la prise en charge de .NET Standard 2.0/.NET Core 2. .
Cependant, je ne trouve aucune extension pour l'intégrer réellement dans l'application Web (par exemple similaire à Ninject.Web.Common )
En regardant le code d'une ancienne solution ASP.NET MVC, j'ai réalisé que tout le mécanisme est différent car le classique s'appuyait sur WebActivatorEx.PreApplicationStartMethod
et WebActivatorEx.ApplicationShutdownMethodAttribute
qui ne sont plus disponibles dans ASP.NET Core.
En outre, l'ancien Ninject.Web.Common
L'assembly a fourni plusieurs classes utiles utilisées pour l'initialisation - Bootstrapper, OnePerRequestHttpModule, NinjectHttpModule:
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
Bootstrapper.Initialize(CreateKernel);
}
Question: existe-t-il un exemple de la façon d'intégrer Ninject dans une application Web ASP.NET Core 2.0?
check ce projet . Cependant, il s'appuie sur Ninject 4.0.0 qui est toujours en version bêta et il semble loin d'être une version finale ( source ). Pour Ninject 3.3.x, regardez ci-dessous.
Grâce à @Steven
, J'ai réussi à créer une solution de travail d'ASP.NET Core 2.0 et Ninject (3.3.x et 4.0). Le code provient principalement de Missing-Core-DI-Extensions Git repo, donc super grâce à dotnetjunkie .
Les opérations suivantes doivent être effectuées quelle que soit la version de Ninject référencée:
1) Inclure AspNetCoreExtensions.cs et AspNetCoreMvcExtensions.cs dans votre projet.
2) Créez un service très simple à utiliser pour tester la DI: TestService
qui implémente ITestService
:
public class TestService : ITestService
{
public int Data { get; private set; }
public TestService()
{
Data = 42;
}
}
public interface ITestService
{
int Data { get; }
}
Modifiez Startup.cs
Comme indiqué ci-dessous:
1) ajouter ces membres
private readonly AsyncLocal<Scope> scopeProvider = new AsyncLocal<Scope>();
private IKernel Kernel { get; set; }
private object Resolve(Type type) => Kernel.Get(type);
private object RequestScope(IContext context) => scopeProvider.Value;
2) Ajouter à ConfigureServices(IServiceCollection services)
(à la fin)
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddRequestScopingMiddleware(() => scopeProvider.Value = new Scope());
services.AddCustomControllerActivation(Resolve);
services.AddCustomViewComponentActivation(Resolve);
3) Ajouter à Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
(au début)
Kernel = RegisterApplicationComponents(app, loggerFactory);
4) Ajoutez la méthode et la classe interne suivantes:
private IKernel RegisterApplicationComponents(
IApplicationBuilder app, ILoggerFactory loggerFactory)
{
// IKernelConfiguration config = new KernelConfiguration();
Kernel = new StandardKernel();
// Register application services
foreach (var ctrlType in app.GetControllerTypes())
{
Kernel.Bind(ctrlType).ToSelf().InScope(RequestScope);
}
Kernel.Bind<ITestService>().To<TestService>().InScope(RequestScope);
// Cross-wire required framework services
Kernel.BindToMethod(app.GetRequestService<IViewBufferScope>);
Kernel.Bind<ILoggerFactory>().ToConstant(loggerFactory);
return Kernel;
}
private sealed class Scope : DisposableObject { }
5) Créer une méthode d'extension BindToMethod
public static class BindingHelpers
{
public static void BindToMethod<T>(this IKernel config, Func<T> method) =>
config.Bind<T>().ToMethod(c => method());
}
6) Testez DI en injectant un service personnalisé dans un contrôleur, en définissant un point d'arrêt dans le constructeur du service de test et en vérifiant la pile d'appels. En plus de fournir une instance, la pile d'appels doit frapper du code personnalisé pour intégrer Ninject (par exemple la méthode ConfigureRequestScoping
)
IKernel
a été déconseillé dans la version 4, donc les classes IReadOnlyKernel et IKernelConfiguration doivent être utilisées (bien que le code ci-dessus devrait fonctionner).
1) Utilisez la nouvelle classe (IReadOnlyKernel
)
private readonly AsyncLocal<Scope> scopeProvider = new AsyncLocal<Scope>();
private IReadOnlyKernel Kernel { get; set; }
private object Resolve(Type type) => Kernel.Get(type);
private object RequestScope(IContext context) => scopeProvider.Value;
2) 3) sont les mêmes
4) La méthode est légèrement différente:
private IReadOnlyKernel RegisterApplicationComponents(
IApplicationBuilder app, ILoggerFactory loggerFactory)
{
IKernelConfiguration config = new KernelConfiguration();
// Register application services
foreach (var ctrlType in app.GetControllerTypes())
{
config.Bind(ctrlType).ToSelf().InScope(RequestScope);
}
config.Bind<ITestService>().To<TestService>().InScope(RequestScope);
// Cross-wire required framework services
config.BindToMethod(app.GetRequestService<IViewBufferScope>);
config.Bind<ILoggerFactory>().ToConstant(loggerFactory);
return config.BuildReadonlyKernel();
}
5) L'extension doit utiliser un IKernelConfiguration
public static class BindingHelpers
{
public static void BindToMethod<T>(
this IKernelConfiguration config, Func<T> method) =>
config.Bind<T>().ToMethod(c => method());
}