我有三个通用接口
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,但我想获得子类。
答案 0 :(得分:6)
您尝试实现的目标只能通过为每种类型创建显式绑定来实现 。毕竟IExpenseCardRepository : IRepositoryBase<ExpenseCard>
与ICustomerRepository : IRepositoryBase<Customer>
不同。
现在好消息是,您可以使用Ninject.Extension.Convention自动执行此类工作。如果你坚持命名约定,它可以很容易地完成。命名约定是:类名以接口名称结尾(当然没有前导I)。从你的代码看起来就像你做的那样。然后解决方案就像:
kernel.Bind(x => x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom(typeof(IServiceBase<>))
.BindDefaultInterfaces());
这会将ExpenseCardService
绑定到IExpenseCardService
和IServiceBase<ExpenseCard>
。
如果您不遵守此命名约定,那么事情就会变得更加复杂:您必须自己提供(自定义)绑定创建部分。您需要做的是实施IBindingGenerator
并使用.BindWith<MyBindingGenerator>()
扩展程序:
kernel.Bind(x => x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom(typeof(IRepositorioBase<>))
.BindWith<MyBindingGenerator>());
然后,您的绑定生成器必须决定将绑定到的类型,并创建并返回这些绑定。
我必须谨慎一点:在大多数情况下,当我看到这种设计时,没有必要(有一个更简单的解决方案)。 一般来说,你应该favor composition over inheritance。