NInject with Generic interface

和自甴很熟 提交于 2019-11-28 16:05:25

This should work:-

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

where:-

IRepository<> is an interface of the form:-

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 holds information about a concrete type and its interfaces. The method IsOpenGeneric is define in the TypeExtensions class.

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.

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. 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? 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 (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();
        }
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!