私はNinjectが最近 。NET Standard 2.0/.NET Core 2.0のサポートを導入 であることを発見しました。
しかし、実際にそれをWebアプリケーションに統合するための拡張機能が見つかりません(例: Ninject.Web.Common に類似)
古いASP.NET MVCソリューションのコードを見ると、ASP.NET Coreでは利用できなくなったWebActivatorEx.PreApplicationStartMethod
とWebActivatorEx.ApplicationShutdownMethodAttribute
に依存していた従来のメカニズムとは異なり、メカニズム全体が異なることに気付きました。
また、古いNinject.Web.Common
アセンブリは、初期化に使用されるいくつかの便利なクラスを提供しました-Bootstrapper、OnePerRequestHttpModule、NinjectHttpModule:
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
Bootstrapper.Initialize(CreateKernel);
}
質問:NinjectをASP.NET Core 2.0 Webアプリケーションに統合する方法の例はありますか?
チェック このプロジェクト 。ただし、それはまだベータ版であるNinject 4.0.0に依存しており、最終版( source )とはかけ離れているようです。 Ninject 3.3.xについては、以下をご覧ください。
_@Steven
_のおかげで、ASP.NET Core 2.0とNinject(3.3.xと4.0の両方)の実用的なソリューションを作成することができました。コードは主に Missing-Core-DI-Extensions Gitリポジトリからのものです。 dotnetjunkie に感謝します。
参照されているNinjectのバージョンに関係なく、以下を実行する必要があります。
1)プロジェクトに AspNetCoreExtensions.cs および AspNetCoreMvcExtensions.cs を含めます。
2)DIのテストに使用する非常に単純なサービスを作成します:TestService
を実装するITestService
:
_public class TestService : ITestService
{
public int Data { get; private set; }
public TestService()
{
Data = 42;
}
}
public interface ITestService
{
int Data { get; }
}
_
以下に示すように_Startup.cs
_を変更します。
1)これらのメンバーを追加する
_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)ConfigureServices(IServiceCollection services)
に追加します(最後に)
_services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddRequestScopingMiddleware(() => scopeProvider.Value = new Scope());
services.AddCustomControllerActivation(Resolve);
services.AddCustomViewComponentActivation(Resolve);
_
3)Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
に追加(最初)
_Kernel = RegisterApplicationComponents(app, loggerFactory);
_
4)次のメソッドと内部クラスを追加します。
_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)BindToMethod
拡張メソッドを作成する
_public static class BindingHelpers
{
public static void BindToMethod<T>(this IKernel config, Func<T> method) =>
config.Bind<T>().ToMethod(c => method());
}
_
6)カスタムサービスをコントローラーに挿入し、テストサービスコンストラクターにブレークポイントを設定して、呼び出しスタックを確認することにより、DIをテストします。インスタンスを提供するほかに、コールスタックはカスタムコードをヒットしてNinjectを統合する必要があります(例:ConfigureRequestScoping
メソッド)
IKernel
はバージョン4で廃止されたため、IReadOnlyKernelクラスとIKernelConfigurationクラスを使用する必要があります(ただし、上記のコードは機能するはずです)。
1)新しいクラス(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)は同じ
4)方法は少し異なります。
_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)拡張機能はIKernelConfiguration
を使用する必要があります
_public static class BindingHelpers
{
public static void BindToMethod<T>(
this IKernelConfiguration config, Func<T> method) =>
config.Bind<T>().ToMethod(c => method());
}
_