具有多个绑定的Ninject错误

时间:2014-05-19 14:12:35

标签: c# asp.net-mvc-4 dependency-injection dependencies ninject

我有一个MVC4应用程序,它使用反射在运行时加载控制器。这些控制器以及主应用程序使用Ninject将内容注入构造函数。

每个动态控制器都维护一个所需的所有绑定列表,并将它们存储为主应用程序在运行时加载的Ninject模块。

我目前在多个动态控制器包含相同绑定时遇到问题。我希望动态控制器是自包含的,所以我不想从控制器项目中删除绑定,我真的不想解析txt或xml文档来读取所有绑定。

有没有办法删除重复绑定或告诉Ninject使用它遇到的第一个绑定(如果有多个绑定)。

加载所有引用的程序集绑定

public static StandardKernel LoadNinjectKernel(IEnumerable<Assembly> assemblies)
{
    var kernel = new StandardKernel();

    foreach (var asm in assemblies)
    {
       asm
       .GetTypes()
       .Where(t =>
              t.GetInterfaces()
                   .Any(i =>
                       i.Name == typeof(INinjectBootstrapper).Name))
            .ToList()
            .ForEach(t =>
            {
                var ninjectModuleBootstrapper =
                    (INinjectBootstrapper)Activator.CreateInstance(t);


                kernel.Load(ninjectModuleBootstrapper.GetModules());
            });
    }

    return kernel;
}

绑定类

public class NinjectBindings : Ninject.Modules.NinjectModule
{
    public override void Load()
    {
        Bind<IDMSService>().To<DMSService>();
        Bind<ICaseManagerRepo>().To<CaseManagerRepo>();
    }
}

控制器工厂

 protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
    {
        if (controllerType != null)
        {                
            return (IController)kernel.Get(controllerType);
        }
        else
        {               
            return base.GetControllerInstance(requestContext, controllerType);
        }                           
    }

1 个答案:

答案 0 :(得分:2)

不,没有。

您可以尝试查看使用IBindingRoot.Rebind代替Bind是否符合您的需要。 但是我会强烈建议反对它,因为它不适用于:

  • 多的结合
  • 条件更改时的条件绑定
  • 在更改
  • 时为绑定添加参数,OnActivation / OnDeactivation,..
  • 这不是线程安全的

即使你让它工作,当你有任何条件,参数,OnActivation / OnDeactivation时,你最终会遇到很多代码重复和难以查明的问题(这些问题是否有效取决于模块加载序列)。这真的不是一条路。

相反,你可以做一直做的事情:消除重复。 将多个位置需要的绑定移动到自己的模块。 创建一些类型(让我们称之为ControllerModules),指定一个控制器需要哪些模块。 找到所有ControllerModules,从中读取模块,然后加载所有这些模块,而不是加载所有模块。

在伪代码中,这可能看起来像:

IEnumerable<Type> modulesToLoad = Assemblies.InPath(...)
          .SelectAllClasses()
          .InheritingFrom<ControllerModules>
          .SelectMany(x => x.RequiredModules)
          .Distinct();
IKernel.Load(modulesToLoad);