使用NInject注册通用接口的泛型类

时间:2015-04-24 00:19:49

标签: c# generics interface ninject

我有三个通用接口

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

我有三个相应的具体泛型类实现

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

,另一个类是使用类泛型创建的,例如

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;
    }
}

我希望通用代码只绑定所有类型的接口 取决于它继承的类的类型

这些是示例Ninject-Generic-Interface,但我想获得子类。

1 个答案:

答案 0 :(得分:6)

您尝试实现的目标只能通过为每种类型创建显式绑定来实现 。毕竟IExpenseCardRepository : IRepositoryBase<ExpenseCard>ICustomerRepository : IRepositoryBase<Customer>不同。 现在好消息是,您可以使用Ninject.Extension.Convention自动执行此类工作。如果你坚持命名约定,它可以很容易地完成。命名约定是:类名以接口名称结尾(当然没有前导I)。从你的代码看起来就像你做的那样。然后解决方案就像:

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

这会将ExpenseCardService绑定到IExpenseCardServiceIServiceBase<ExpenseCard>

如果您不遵守此命名约定,那么事情就会变得更加复杂:您必须自己提供(自定义)绑定创建部分。您需要做的是实施IBindingGenerator并使用.BindWith<MyBindingGenerator>()扩展程序:

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

然后,您的绑定生成器必须决定将绑定到的类型,并创建并返回这些绑定。

我必须谨慎一点:在大多数情况下,当我看到这种设计时,没有必要(有一个更简单的解决方案)。 一般来说,你应该favor composition over inheritance