N注入通用接口

我定义了一个接口和一个类:

public interface IRepository<T> { } public class RoleRepository:IRepository<Domain_RoleInfo> { } 

在这里注入:

 public RoleService { [Inject] public RoleService(IRepository<Domain_RoleInfo> rep) { _roleRep=rep; } } 

如何执行Ninject的dependency injection,说如何绑定?

我已经写了一个助手类,如下所示,它与非通用接口工作正常。但如何重构它支持通用接口如上?

 public class RegisterNinjectModule : NinjectModule { public override void Load() { BindServices(); BindRepositories(); } private void BindServices() { FindAndBindInterfaces("RealMVC.Service.Interfaces", "RealMVC.Services"); } private void BindRepositories() { FindAndBindInterfaces("RealMVC.Repository.Interfaces", "RealMVC.Repositories"); } private void FindAndBindInterfaces(string interfaceAssemblyName, string implAssemblyName) { //Get all interfaces List<Type> interfaces = Assembly.Load(interfaceAssemblyName).GetTypes().AsQueryable().Where(x => x.IsInterface).ToList(); IQueryable<Type> ts = Assembly.Load(implAssemblyName).GetTypes().AsQueryable().Where(x => x.IsClass); foreach (Type intf in interfaces) { Type t = ts.Where(x => x.GetInterface(intf.Name) != null).FirstOrDefault(); if (t != null) { Bind(intf).To(t).InSingletonScope(); } } } } 

这应该工作: –

 Bind(typeof(IRepository<>)).To(typeof(Repository<>)); 

哪里:-

IRepository <>是以下forms的接口:

 public interface IRepository<T> where T : class { //... } 

Repository <>是一个forms的类: –

 public class Repository<T> : IRepository<T> where T : class { //... } 

我希望这有帮助 :-)

这应该有助于完成你所要求的。

首先让我们定义两个类( InterfaceTypeDefinitionBindingDefinition )。

InterfaceTypeDefinition保存有关具体types及其接口的信息。 IsOpenGeneric方法在TypeExtensions类中定义。

 public class InterfaceTypeDefinition { public InterfaceTypeDefinition(Type type) { Implementation = type; Interfaces = type.GetInterfaces(); } /// <summary> /// The concrete implementation. /// </summary> public Type Implementation { get; private set; } /// <summary> /// The interfaces implemented by the implementation. /// </summary> public IEnumerable<Type> Interfaces { get; private set; } /// <summary> /// Returns a value indicating whether the implementation /// implements the specified open generic type. /// </summary> public bool ImplementsOpenGenericTypeOf(Type openGenericType) { return Interfaces.Any(i => i.IsOpenGeneric(openGenericType)); } /// <summary> /// Returns the service type for the concrete implementation. /// </summary> public Type GetService(Type openGenericType) { return Interfaces.First(i => i.IsOpenGeneric(openGenericType)) .GetGenericArguments() .Select(arguments => openGenericType.MakeGenericType(arguments)) .First(); } } 

BindingDefinition保存有关服务和具体实现之间绑定的信息。

 public class BindingDefinition { public BindingDefinition( InterfaceTypeDefinition definition, Type openGenericType) { Implementation = definition.Implementation; Service = definition.GetService(openGenericType); } public Type Implementation { get; private set; } public Type Service { get; private set; } } 

其次,让我们实现一个检索必要信息的扩展方法。

 public static class TypeExtensions { public static IEnumerable<BindingDefinition> GetBindingDefinitionOf( this IEnumerable<Type> types, Type openGenericType) { return types.Select(type => new InterfaceTypeDefinition(type)) .Where(d => d.ImplementsOpenGenericTypeOf(openGenericType)) .Select(d => new BindingDefinition(d, openGenericType)); } public static bool IsOpenGeneric(this Type type, Type openGenericType) { return type.IsGenericType && type.GetGenericTypeDefinition().IsAssignableFrom(openGenericType); } } 

现在可以使用这些类来初始化模块中的绑定。

 public class RepositoryModule : NinjectModule { public override void Load() { var definitions = Assembly.GetExecutingAssembly().GetTypes() .GetBindingDefinitionOf(typeof(IRepository<>)); foreach (var definition in definitions) { Bind(definition.Service).To(definition.Implementation); } } } 

如果您导入Ninject约定扩展,它的GenericBindingGenerator应该能够帮助您。 它增加了对通用接口的支持。

只是在你的FindAndBindInterfaces方法上的一个问题:在foreach里面你没有intfvariables的“closures”问题? 我仍然不确定我是否理解封闭问题是如何工作的。

无论如何,为了安全起见,我认为你应该改变你的习惯为:

 foreach (Type intf in interfaces) { var tmp = intf; Type t = ts.Where(x => x.GetInterface(tmp.Name) != null).FirstOrDefault(); if (t != null) { Bind(intf).To(t).InSingletonScope(); } }