加载NinjectModule的顺序

时间:2014-07-29 03:17:16

标签: c# asp.net asp.net-mvc ninject

我在ASP.NET MVC项目中安装了Ninject.Web.Common NuGet包:

public static class NinjectWebCommon 
{
    private static readonly Bootstrapper Bootstrapper = new Bootstrapper();

    /// <summary>
    /// Starts the application
    /// </summary>
    public static void Start() 
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        Bootstrapper.Initialize(CreateKernel);
    }

    /// <summary>
    /// Stops the application.
    /// </summary>
    public static void Stop()
    {
        Bootstrapper.ShutDown();
    }

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Load(Assembly.GetExecutingAssembly());
    }        
}

请注意,当我从kernel.Load(Assembly.GetExecutingAssembly())派生时,我使用NinjectModule自动注册我的绑定。但是我有需要在NinjectModule

中解决的依赖项
public class NinjectModuleA : NinjectModule
{
    public override void Load()
    {
        Bind<ILogger>().To<Log4NetLogger>().InSingletonScope();
    }
}

public class NinjectModuleB : NinjectModule
{
    public override void Load()
    {
        Bind<IRepository>()
          .To<Repository>()
          .WithConstructorArgument(typeof(ILogger), Kernel.Get<ILogger>())
          .InRequestScope();
    }
}

以某种方式NinjectModuleBNinjectModuleA之前加载了ActivationException,这给了我一个ILogger

  

激活ILogger时出错   没有匹配的绑定可用,并且该类型不可自绑定。   激活路径:   1)请求ILogger

这是可以理解的,因为调用NinjectB.LoadNinjectModuleA的绑定不可用。有什么方法可以告诉Ninject NinjectModuleB之前必须加载{{1}}吗?

1 个答案:

答案 0 :(得分:6)

您正在错误地使用IoC。 这个想法是,ILogger被注入到对象的ctor中。除特殊情况外,您无需指定要使用的构造函数参数。 默认情况下,ninject将查找合适的构造函数并尝试解析所有构造函数参数。所以你根本不需要WithConstructorArgument(...)。 而你所需要的只是:

public class Repository
{
    public Repository(ILogger logger) { }
}

Bind<Ilogger>().To(... some binding...);
Bind<IRepository>().To<Repository>();

IRepository repository = kernel.Get<IRepository>(); // creates an instance of `Repository` and injects an `ILogger` - which is to be resolved as specified by the `Bind<Ilogger>.To...` binding.

如果您绝对需要控制加载顺序,则必须自己实施该部分,然后使用IKernel.Load<T> : where T : INinjectModuleIKernel.Load(INinjectModule module)

但是,您应该尽可能地调整您的设计,以便不需要这些依赖关系。对于你目前的情况,你所要做的就是替换

WithConstructorArgument(typeof(ILogger), Kernel.Get<ILogger>())

通过

WithConstructorArgument(typeof(ILogger), ctx => ctx.Kernel.Get<ILogger>());

但是,正如已经说过的那样,你可以完全摆脱WithConstructorArgument