为具有 NInject 的通用接口注册通用 类
Registering generic classes for generic interfaces with NInject
我有三个通用接口
public interface IRepositorioBase<T> where T : class { }
public interface IServiceBase<T> where T : class {}
public interface IAppBase<T> where T : class {}
为此我有三个相应的具体通用 class 实现
public class RepositorioBase<T> where T : class { }
public class ServiceBase<T> where T : class {}
public class AppBase<T> where T : class {}
和其他 class 是使用 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;
}
}
我想要一个通用代码只绑定所有类型的接口
取决于它继承
的class的类型
这些是例子 Ninject-Generic-Interface 但我想得到 subclass.
您要实现的目标只能通过为每种类型创建显式绑定来完成。毕竟 IExpenseCardRepository : IRepositoryBase<ExpenseCard>
不同于 ICustomerRepository : IRepositoryBase<Customer>
。
现在好消息是,您可以使用 Ninject.Extension.Convention 自动执行此类工作。如果你坚持一个命名约定,它可以很容易地完成。命名约定是:Class 名称以接口名称结尾(当然没有前导 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>());
然后您的绑定生成器必须决定将哪些类型绑定 到 并创建和 return 这些绑定。
不过,我必须提醒一句:在大多数情况下,当我看到这种设计时,它是没有必要的(有一个更简单的解决方案可用)。
一般来说,你应该 favor composition over inheritance.
我有三个通用接口
public interface IRepositorioBase<T> where T : class { }
public interface IServiceBase<T> where T : class {}
public interface IAppBase<T> where T : class {}
为此我有三个相应的具体通用 class 实现
public class RepositorioBase<T> where T : class { }
public class ServiceBase<T> where T : class {}
public class AppBase<T> where T : class {}
和其他 class 是使用 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;
}
}
我想要一个通用代码只绑定所有类型的接口 取决于它继承
的class的类型这些是例子 Ninject-Generic-Interface 但我想得到 subclass.
您要实现的目标只能通过为每种类型创建显式绑定来完成。毕竟 IExpenseCardRepository : IRepositoryBase<ExpenseCard>
不同于 ICustomerRepository : IRepositoryBase<Customer>
。
现在好消息是,您可以使用 Ninject.Extension.Convention 自动执行此类工作。如果你坚持一个命名约定,它可以很容易地完成。命名约定是:Class 名称以接口名称结尾(当然没有前导 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>());
然后您的绑定生成器必须决定将哪些类型绑定 到 并创建和 return 这些绑定。
不过,我必须提醒一句:在大多数情况下,当我看到这种设计时,它是没有必要的(有一个更简单的解决方案可用)。 一般来说,你应该 favor composition over inheritance.