2010-02-07 16 views
41

he definido una interfaz y una clase:ninject con interfaz genérica

public interface IRepository<T> 
{ 
} 

public class RoleRepository:IRepository<Domain_RoleInfo> 
{ 
} 

Inyectar aquí:

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

¿Cómo puedo realizar la inyección de dependencias Con Ninject, decir cómo enlazar?

He escrito una clase de ayuda como la siguiente, funciona bien con una interfaz no genérica. ¿Pero cómo refactorizarla es compatible con la interfaz genérica como la anterior?

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(); 
      } 
     } 
    } 


} 

Respuesta

5

Esto debería ayudar a lograr lo que está solicitando.

Primero permítanos definir dos clases (InterfaceTypeDefinition y BindingDefinition).

InterfaceTypeDefinition contiene información sobre un tipo de hormigón y sus interfaces. El método IsOpenGeneric se define en la clase 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 contiene información sobre la unión entre un servicio y una aplicación concreta.

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; } 
} 

En segundo lugar, implementemos un método de extensión que recupere la información necesaria.

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); 
    } 
} 

Estas clases ahora se pueden utilizar para inicializar los enlaces en el módulo.

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); 
     } 
    } 
} 
+0

Gracias. esto es exactamente lo que estaba buscando cuando hice esta pregunta: http://stackoverflow.com/questions/11702477/binding-generic-types-in-ninject-3-0 Hay un error tipográfico en TypeExtensions.GetBindingDefintionOf() - debe pasar 'd' en lugar de 'definición' al crear BindingDefinition en el método Select. – Baldy

78

Esto debería funcionar: -

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

donde: -

IRepository <> es una interfaz de la forma: -

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

Repositorio <> es una clase de la forma: -

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

Espero que esto ayude :-)

+0

¿Cómo se vería la inyección del constructor? – chobo2

+0

@ chobo2 ver la publicación original? – Izmoto

+1

¿funciona sin "donde T: clase"? – Boinst

0

Sólo una pregunta en sus FindAndBindInterfaces método: en el interior del foreach no tiene un problema de "cierre" en la variable intf? Todavía no estoy seguro de haber entendido cómo funciona el problema del cierre.

De todos modos, sólo para estar seguro, creo que debe cambiar su foreach en algo así como:

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(); 
     } 
    } 
2

Si importa la extensión convenciones Ninject, su GenericBindingGenerator debe ser capaz de ayudarle. Agrega soporte para interfaces genéricas.

+2

¿Cómo ayuda? –

+0

Actualicé mi respuesta. Agrega soporte para interfaces genéricas. – neontapir

Cuestiones relacionadas