Ninject通过绑定不公约泛型类型的工作 [英] Ninject Binding by Convention not working with generics types

查看:254
本文介绍了Ninject通过绑定不公约泛型类型的工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用.NET 4.5,Ninject 3 按照惯例LIB 作为绑定如下:



<预类=郎-CS prettyprint-覆盖> kernel.Bind(X => X
.FromAssembliesMatching( assembly.dll)
.SelectAllClasses()InheritedFrom(typeof运算(ICommandHandler<>))
.BindAllInterfaces());



这是正确约束力的:



<预类=郎-CS prettyprint-覆盖> 公共类MyCommandHandler:ICommandHandler< MyCommand>



绑定:



<预类=郎-CS prettyprint-覆盖> 公共类MyGenericCommandHandler< T> :ICommandHandler< MyGenericCommand< T>>



不过,以前的绑定工作,如果我增加对具体的实现我的泛型类的,如个人绑定



<预类=郎-CS prettyprint-覆盖> kernel.Bind(typeof运算(ICommandHandler< MyGenericCommand<浮动>>))
。要(typeof运算(MyGenericCommandHandler<浮动>))
kernel.Bind(typeof运算(ICommandHandler< MyGenericCommand< INT>>))
。要(typeof运算(MyGenericCommandHandler< INT>))

但添加每个单独的一般类型违背约定的目的,需要添加对每个可能的个别类型如浮动结合,整型,字符串,等等...




你知道如何修改公约或添加另一个(或甚至
配备了一个完全不同的解决方案),以支持我的命令的通用
版本? 。即支持两个级别的仿制药



解决方案

编辑:不能编译[和事实它不显示的要求没有意义],请推理这个结论中的注释。






这只是常开仿制药的情况下。正如我在先前的评论的链接提到,顺便基本绑定使该DRY看起来很简单:

 内核。绑定(typeof运算(ICommandHandler< MyGenericCommand<>>))
。要(typeof运算(MyGenericCommandHandler<>));

这绑定,然后将足以满足任何 T 变种 ICommandHandler< MyGenericCommand< T>>



在做约定基于它绑定到映射上下文你期待什么,问题是, SelectAllClasses()InheritedFrom(typeof运算(ICommandHandler<>))。不包括泛型类 - 这是有道理的,因为它是罕见的您可以指定非具体的类通用的规则。



您可以




  • 使用DSL不同的投影部分,选择通用类,然后以某种约定基础的方式将它们绑定

  • 暴露 NinjectModule 从组件露出它可以完成上述绑定,然后做的 kernel.Load() [打开]通用服务模块[由DLL名称模式的概率。


I am using .NET 4.5, Ninject 3 with the binding by convention lib as follow:

kernel.Bind(x => x
    .FromAssembliesMatching("assembly.dll")
    .SelectAllClasses().InheritedFrom(typeof(ICommandHandler<>))
    .BindAllInterfaces());

And this is binding properly for:

public class MyCommandHandler : ICommandHandler<MyCommand>

But doesn't bind:

public class MyGenericCommandHandler<T> : ICommandHandler<MyGenericCommand<T>>

However, the previous binding works if I add individual bindings for specific implementation of my generics class, such as:

kernel.Bind(typeof(ICommandHandler<MyGenericCommand<float>>))
      .To(typeof(MyGenericCommandHandler<float>))
kernel.Bind(typeof(ICommandHandler<MyGenericCommand<int>>))
      .To(typeof(MyGenericCommandHandler<int>))

But adding each individual generic type defeats the purpose of conventions and require adding binding for each possible individual type such as float, int, string, etc...

Do you know how to modify the convention or add another one (or even come with a completely different solution) to support the generic version of my command? i.e. supporting two-level generics.

解决方案

EDIT: Doesn't compile [and the fact it doesn't reveals the requirement doesn't make sense], see reasoning for this conclusion in the comments.


This is just the normal open generics case. As alluded to with a link in my earlier comment, the way a basic bind to make that DRY looks is simply:

kernel.Bind(typeof(ICommandHandler<MyGenericCommand<>>))
    .To(typeof(MyGenericCommandHandler<>));

This binding will then suffice for any T variant of ICommandHandler<MyGenericCommand<T>>.

In the context of doing convention based binding it to mapping what you're expecting, the problem is that SelectAllClasses().InheritedFrom(typeof(ICommandHandler<>)) does not include generic classes -- this makes sense as it's rare that you can specify generalized rules on non concrete classes.

You can either

  • use a different Projection portion of the DSL to select the Generic classes and then bind them in some convention based manner
  • expose a NinjectModule from assemblies exposing [open] generic services which does the above Bind and then do a kernel.Load() of the module [prob by the DLL name pattern].

这篇关于Ninject通过绑定不公约泛型类型的工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆