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 { //... }
我希望这有帮助 :-)
这应该有助于完成你所要求的。
首先让我们定义两个类( InterfaceTypeDefinition
和BindingDefinition
)。
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(); } }