简体   繁体   English

使用NInject为通用接口注册通用类

[英]Registering generic classes for generic interfaces with NInject

I Have three generic interfaces 我有三个通用接口

public interface IRepositorioBase<T> where T : class {    }
public interface IServiceBase<T> where T : class {}
public interface IAppBase<T> where T : class {}

for which I have three corresponding concrete generic class implementations 为此,我有三个对应的具体泛型类实现

public class RepositorioBase<T> where T : class {    }
public class ServiceBase<T> where T : class {}
public class AppBase<T> where T : class {}

and the other class are create using the class generics, example 另一个类是使用类泛型创建的,例如

public class ExpenseCardRepository : RepositoryBase<ExpenseCard>, IExpenseCardRepository{ }

public class ExpenseCardService : ServiceBase<ExpenseCard>, IExpenseCardService
{
    private readonly IExpenseCardRepository _repository;

    public ExpenseCardService(IExpenseCardRepository repository) : base(repository)
    {
        _repository = repository;
    }
}

public class ExpenseCardApp : AppBase<ExpenseCard>, IExpenseCardApp
{
    private readonly IExpenseCardService _service;

    public ExpenseCardApp(IExpenseCardService service) : base(service)
    {
        _service = service;
    }
}

I would like a generic code only to bind all types of interfaces depending on the type of class it inherits 我只希望通用代码根据其继承的类的类型来绑定所有类型的接口

These is example Ninject-Generic-Interface but I would like get of subclass. 这些是示例Ninject-Generic-Interface,但我想获取子类。

What you're trying to achieve can only be done by creating an explicit binding for each type. 什么你想实现只能通过创建一个明确的结合每种类型来完成。 After all IExpenseCardRepository : IRepositoryBase<ExpenseCard> is different from ICustomerRepository : IRepositoryBase<Customer> . 毕竟IExpenseCardRepository : IRepositoryBase<ExpenseCard>ICustomerRepository : IRepositoryBase<Customer> Now the good news is that you can automate this kind of work, by using Ninject.Extension.Convention . 现在,好消息是您可以使用Ninject.Extension.Convention来自动化此类工作。 If you stick to a naming convention, it can be done very easy. 如果您遵循命名约定,则可以非常轻松地完成。 The naming convention is: Class name ends with the interface name (without a leading I of course). 命名约定为:类名以接口名结尾(当然,不带前导I)。 From your code it looks like you do. 从您的代码看起来像您一样。 Then the solution is as easy as: 然后,解决方案很简单:

kernel.Bind(x => x.FromThisAssembly()
    .SelectAllClasses()
    .InheritedFrom(typeof(IServiceBase<>))
    .BindDefaultInterfaces());

This will bind ExpenseCardService to IExpenseCardService and IServiceBase<ExpenseCard> . 这会将ExpenseCardService绑定到IExpenseCardServiceIServiceBase<ExpenseCard>


If you don't adhere to this naming convention, then things get a little more complicated: you'll have to provide (customize) the binding creation part yourself. 如果您不遵守此命名约定,那么事情会变得更加复杂:您必须自己提供(自定义)绑定创建部分。 What you would have to do is implement an IBindingGenerator and use the .BindWith<MyBindingGenerator>() extension: 您要做的是实现IBindingGenerator并使用.BindWith<MyBindingGenerator>()扩展名:

kernel.Bind(x => x.FromThisAssembly()
                  .SelectAllClasses()
                  .InheritedFrom(typeof(IRepositorioBase<>))
                  .BindWith<MyBindingGenerator>());

Your binding generator would then have to decide which types to bind to and create and return those bindings. 然后,绑定生成器将必须决定要绑定到的类型并创建并返回这些绑定。


I have to give a word of caution, though: in most cases when i've seen this kind of design it was not necessary (there was a simpler solution available). 但是,我必须提个警告:在大多数情况下,当我看到这种设计时,这是没有必要的(有一个更简单的解决方案可用)。 In general you should favor composition over inheritance . 通常,您应该更喜欢使用组合而不是继承

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM