多重绑定时出现 Ninject 错误

问题描述 投票:0回答:2

我有一个 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
2个回答
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);

0
投票

现在已经过去十多年了,但这也许可以帮助有类似问题的人。

我能够使用此扩展方法避免重复注册:

public IBindingToSyntax<T> TryBind<T>(this IKernel instance)
{
    IBindingToSyntax<T> builder;
    IBinding binding;
    Type type;

    type = typeof(T);
    binding = instance.GetBindings(typeof(T)).FirstOrDefault;

    if (binding == null)
    {
        binding = new Binding(type);
        instance.AddBinding(binding);
    }

    builder = new BindingBuilder<T>(binding, instance, type.Format);

    return builder;
}

用途:

container.TryBind(Of IDotNetService).To(Of DotNetService)()

注意:这不适用于命名绑定,因为我们目前不知道我们将使用命名绑定。

© www.soinside.com 2019 - 2024. All rights reserved.