[英]NInject with Generic interface
I have defined one interface and one class: 我已经定义了一个接口和一个类:
public interface IRepository<T>
{
}
public class RoleRepository:IRepository<Domain_RoleInfo>
{
}
Inject here: 在这里注入:
public RoleService
{
[Inject]
public RoleService(IRepository<Domain_RoleInfo> rep)
{
_roleRep=rep;
}
}
How can I perform Dependency Injection With Ninject,say how to bind? 如何使用Ninject执行依赖注入,说明如何绑定?
I have written a helper class as below, it works fine with non-generic interface.but how to refactor it support generic interface as above? 我已经编写了一个如下所示的辅助类,它可以与非泛型接口一起工作。但是如何重构它支持如上所述的通用接口?
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();
}
}
}
}
This should work:- 这应该工作: -
Bind(typeof(IRepository<>)).To(typeof(Repository<>));
where:- 哪里:-
IRepository<> is an interface of the form:- IRepository <>是以下形式的接口: -
public interface IRepository<T> where T : class
{
//...
}
Repository<> is a class of the form:- 存储库<>是一种形式的类: -
public class Repository<T> : IRepository<T> where T : class
{
//...
}
I hope this helps :-) 我希望这有帮助 :-)
This should help accomplish what you are asking for. 这应该有助于实现您的要求。
First let us define two classes ( InterfaceTypeDefinition
and BindingDefinition
). 首先让我们定义两个类(
InterfaceTypeDefinition
和BindingDefinition
)。
InterfaceTypeDefinition
holds information about a concrete type and its interfaces. InterfaceTypeDefinition
包含有关具体类型及其接口的信息。 The method IsOpenGeneric
is define in the TypeExtensions
class. 方法
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
holds information about the binding between a service and a concrete implementation. 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; }
}
Second, let us implement an extension method that retrieves the necessary information. 其次,让我们实现一个检索必要信息的扩展方法。
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);
}
}
These classes can now be used to initialize the bindings in the module. 现在可以使用这些类初始化模块中的绑定。
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);
}
}
}
If you import the Ninject conventions extension, its GenericBindingGenerator
should be able to help you. 如果您导入Ninject约定扩展,其
GenericBindingGenerator
应该能够帮助您。 It adds support for generic interfaces. 它增加了对通用接口的支持。
Just a question on your FindAndBindInterfaces method: inside the foreach don't you have a "closure" problem on the intf variable? 只是关于FindAndBindInterfaces方法的一个问题:在foreach内部,你对intf变量没有“闭包”问题吗? I'm still not sure I understood how the closure issue works.
我仍然不确定我是否理解闭包问题是如何工作的。
Anyway, just to be safe, I think that you should change your foreach into something like: 无论如何,为了安全起见,我认为你应该将你的foreach改成:
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();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.