【问题标题】:How to bind services with Ninject Conventions如何使用 Ninject 约定绑定服务
【发布时间】:2014-03-04 07:59:55
【问题描述】:

我想用 Ninject.Extensions.Conventions 解决两个场景。

第一个是一个简单的例子:每当请求来自名称空间的包含“服务”一词的实例时,返回唯一匹配类的单例实例。我试过这样:

Kernel.Bind(service => service.FromThisAssembly()
                              .Select(theClass => theClass.Namespace.Contains("Service"))
                              .BindDefaultInterface()
                              .Configure(binding => binding.InSingletonScope()));

其中一些服务得到了解析,但是当解析链到达Impl1 具有IService2 依赖项的点时,我遇到了ActivationException

这个绑定有什么问题?


第二个可能同样简单。所有继承BaseClass 的类都应该通过一个方法来实例化。这是我到目前为止使用的解析代码,按类执行此操作:

Bind<MyViewModel>().ToMethod(ctx => fac.CreateProxy<MyViewModel>())
                   .InSingletonScope();

[ 注意:在本例中,fac 是构建 Castle 代理的自定义工厂。]

对于从ViewModelBaseExtensions.Conventions 继承的类,我该如何做这样的事情?

我已经找到了选择部分,就在这里。

Kernel.Bind(ViewModel => ViewModel.FromThisAssembly()
                                  .Select(t => t.BaseType == typeof(ViewModelBase))
                                  );

现在我需要让那个工厂投入使用......


一般问题:

  1. Extensions.Conventions 的绑定方式似乎与常规方式完全相反:

    • 忍者:Bind &lt;Interface&gt;() . To &lt;Implementation&gt; ()

    • 约定:SelectAllClasses().BindDefaultInterface()

      为什么会这样,还是我误解了这个?

  2. 我曾经将我的绑定放在派生自 NinjectModule 的类中,而且我最好继续这样做。使用Extensions.Conventions 时有什么不这样做的原因吗?

【问题讨论】:

  • 关于您的第一个示例,您能否发布示例您如何尝试从服务命名空间解析类型?
  • 那里有样例,第一个代码sn -p
  • 不,那是注册部分,我对您如何使用/解析注册类型感兴趣,所以您会得到一个ActivationException
  • 啊,好的。我会将那部分添加到帖子中
  • 我更新了帖子,问题和我想的有点不一样……

标签: dependency-injection ninject conventions ninject-extensions


【解决方案1】:

第一: 请发布确切的 ActivationException 消息 + Stacktrace。 很可能缺少IService2 的绑定或存在循环依赖。

: 使用绑定生成器:

    public override void Load()
    {
        this.Bind(x => x
            .FromThisAssembly()
            .SelectAllClasses()
            .InheritedFrom<BaseClass>()
            .BindWith<ToSelfProxyBindingGenerator>()
            .Configure(binding => binding.InSingletonScope()));
    }

    public class ToSelfProxyBindingGenerator : IBindingGenerator
    {
        public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
        {
            yield return bindingRoot
                .Bind(type)
                .ToMethod(ctx => fac.CreateProxy(type));
        }
    }

另请注意,可以使用IBindingGenerator 或@ 约定使用.Configure(..) 方法定义单例范围。

一般问题

  1. 你是对的,但我不能告诉你背后的确切原因。
  2. 不,将约定放入不同的模块是完全可以的。我们也在这样做,而且效果很好。

【讨论】:

  • 感谢您的回复。首先,感谢您的示例代码 - 它工作正常。尽管如此,我有时仍需要使用附加参数调用fac.CreateProxy(type)。我怎样才能把那些传进去?有点违背惯例的想法,不是吗?
  • 依赖于特定类型的附加参数肯定超出了约定范围。根据成本,您可以选择将它们过滤掉并单独绑定它们,或者您可以调整 BindingGenerator 以找出参数是什么并传递它们。有没有一种方法可以通用地识别参数(通过反射,...)以及如何获取参数的值(可能通过依赖注入?)?你可能想看看github.com/ninject/ninject.extensions.factory,看看那里是如何进行参数识别和解析的。
  • 非常感谢,您的代码和解释对我帮助很大!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-29
  • 1970-01-01
相关资源
最近更新 更多