简体   繁体   English

带有通用接口的NInject

[英]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 ). 首先让我们定义两个类( InterfaceTypeDefinitionBindingDefinition )。

InterfaceTypeDefinition holds information about a concrete type and its interfaces. InterfaceTypeDefinition包含有关具体类型及其接口的信息。 The method IsOpenGeneric is define in the TypeExtensions class. 方法IsOpenGenericTypeExtensions类中定义。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM