2017-03-05 62 views
0

注入通用接口为MVC控制器我有以下情况:如何使用Ninject

  • 接口:

    public interface ITest<T> where T:class 
    { 
        void Delete(T item); 
    } 
    
  • 抽象实现:

    public abstract class Test<T>:ITest<T> where T:class 
        { 
         private readonly ApplicationDbContext _context; 
    
         protected Test(ApplicationDbContext context){ 
         _context=context; 
         } 
         public void Delete(T item) { } 
        } 
    
  • 最终课程:

    public class RepoTest:Test<FirstEntity> 
    { 
        public void DoSomething() { } 
    } 
    

我有一个MVC控制器,它看起来像这样:

public abstract class MyController<T>:Controller where T:class 
    { 
     private readonly ITest<T> _test; 
     protected MyController(ITest<T> test) 
     { 
      _test = test; 
     } 
    } 

对于每个实体,我创建了一个控制器,从myController的继承,并在实体基础我想ninject具体注入类。

为此,我尝试使用这个绑定:

kernel.Bind(typeof(ITest<>)).To(typeof(Test<>)).InRequestScope(); 

      kernel.Bind(x=>x.FromAssemblyContaining(typeof(Test<>)) 
      .SelectAllClasses() 
      .InheritedFrom(typeof(Test<>)) 
      .BindToSelf()); 

不幸的是我alwasys了这种错误的:

错误激活ITEST {工具} 没有匹配的绑定是可用的,并且类型不可自行绑定。 激活路径:依赖ITEST {工具}的 2)注入用于ToolsController

类型的构造ToolsController 1)请求的参数测试

建议:1)确保您已经定义了 ITEST {工具}绑定。 2)如果在模块中定义了绑定,请确保该模块已加载到内核中。 3)确保你没有 意外创建了多个内核。 4)如果您正在使用 构造函数参数,请确保参数名称与 构造函数参数名称匹配。 5)如果您正在使用自动模块 加载,请确保搜索路径和过滤器是正确的。

我该如何告诉Ninject,要将实体类型的类基础注入?

+0

异常文本引用类'ToolsController',它不在列表中。你能拿出来吗? – zaitsman

+0

此外,请显示'Test ' – zaitsman

+0

的构造函数我编辑了我的帖子,现在可见构造函数。我正在寻找一种有bacth绑定方法的方法,因为我有更多的50个实体。 –

回答

1

当前写入的代码不起作用。

你有两个选择:

  1. 使用通用:

由于控制器期待ITest<T>这势必Test<T>abstract类不能被实例化。

你必须做一个具体但通用的类Test<T>并添加绑定ApplicationDbContext这将自动工作。

  • 使用反射在结合找到合适的类型,例如:
  • 重要!!!删除您的kernel.Bind()电话。

    // this will find classes which, like RepoTest, are derived from Test<> 
    var allDerivedTypes = typeof(Test<>).Assembly.GetExportedTypes().Where(x => x.BaseType.IsGenericType && x.BaseType.GetGenericTypeDefinition() == typeof(Test<>)).ToList(); 
    
    // ideally, you'd find some way to constrain all your models. 
    // what you need for this foreach is all of the entities that can be present in things like RepoTest 
    foreach(var t in typeof(Tool).Assembly.GetExportedTypes()) 
    { 
        // For each entity, get a runtime representation of Test<Entity> 
        var targetType = typeof(Test<>).MakeGenericType(t); 
    
        // Check if there is a class derived from Test<Entity> 
        var potentiallyPresentImplementation = allDerivedTypes.FirstOrDefault(x => targetType == x.BaseType); // here you might want to decide how to handle multiple instances of the same generic base 
    
        // Found one, so bind it 
        if(potentiallyPresentImplementation != null) 
        { 
         kernel.Bind(targetType).To(potentiallyPresentImplementation).InRequestScope(); 
        } 
    } 
    

    注意:方法2当前是假设所有模型和Test<>衍生物是在一个assmebly,respecitvely。如果情况并非如此,则需要添加更多反射魔法来检查所有引用的程序集。

    之后,控制器将获得RepoTest注入。虽然说实话,方法1.更好:)