【问题标题】:Ninject Error with multiple bindings具有多个绑定的 Ninject 错误
【发布时间】:2014-07-07 13:09:57
【问题描述】:

我有一个 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);
        }                           
    }

【问题讨论】:

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


    【解决方案1】:

    不,没有。

    您可以尝试使用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);
    

    【讨论】:

    • 感谢您的回复,我觉得我需要重新调整我的工作方式。我真的不想硬编码任何东西,所以我可能会重构代码,以便模块返回一些我可以在加载绑定之前解析的内容,这样我就不会得到任何重复。
    猜你喜欢
    • 2019-12-01
    • 2011-04-26
    • 1970-01-01
    • 2011-04-10
    • 2011-10-08
    • 2019-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多