Ninject doesn't resolve dependencies for OWIN

2019-06-13 17:36发布

问题:

public class WebAppHost {

    public WebAppHost(IAppSettings appSettings) {
        this._appSettings = appSettings;
    }

    public Configuration(IAppBuilder appBuilder) {
        if(this._appSettings.StartApi)
            appBuilder.UseWebApi();
    }

}

public class AppContext {

    public static void Start(string[] args) {

        DynamicModule.Utility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModule.Utility.RegisterModule(typeof(NinjectHttpModule));

        _bootstrapper.Initialize(CreateKernel);
        WebApp.Start<WebAppHost>("uri");

    }

    private static IKernel CreateKernel() {
        var kernel = new StandardKernel();
        kernel.bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
        RegisterServices(kernel);
        return kernel;
    }

    private static void ReigsterServices(IKernel kernel) {
        kernel.Bind<IAppSettings>().To<AppSettings>()
            .InRequestScope();
    }

} 

When I try to access the resolved IAppSettings, it's always null and a null reference exception occurs. What could be wrong?

回答1:

The OWIN startup will create your WebAppHost instance for you without using your container. In order to perform the startup with a class that has been injected, use the following code:

public class AppContext {
    //[...]

    public static void Start(string[] args) {
        //[...]
        _bootstrapper.Initialize(CreateKernel);

        //Remember to dispose this or put around "using" construct.
        WebApp.Start("uri", builder =>
        {
            var webHost = _bootstrapper.Kernel.Get<WebAppHost>();
            webHost.Configuration(builder);
        } );
    }

    //[...]
}

This will call Configuration method in your WebAppHost instance with your IAppSettings injected.

PS: As a suggestion, I think you shouldn't use InRequestScope() for your IAppSettings binding in RegisterServices. Use singleton, transient or custom scope for that. From my experience you wouldn't need any application settings that are bound to a request scope.