2010-02-07 4 views
41

я определил один интерфейс и один класс:Ninject с общим интерфейсом

public interface IRepository<T> 
{ 
} 

public class RoleRepository:IRepository<Domain_RoleInfo> 
{ 
} 

Вводят здесь:

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

Как я могу выполнить Dependency Injection с Ninject, скажем, как связать?

Я написал вспомогательный класс, как показано ниже, он отлично работает с не общим интерфейсом. Но как его реорганизовать, он поддерживает общий интерфейс, как указано выше?

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


} 

ответ

5

Это должно помочь выполнить то, о чем вы просите.

Сначала давайте определим два класса (InterfaceTypeDefinition и BindingDefinition).

InterfaceTypeDefinition содержит информацию о конкретном типе и его интерфейсах. Метод 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); 
     } 
    } 
} 
+0

Спасибо. это именно то, что я искал, когда задавал этот вопрос - http://stackoverflow.com/questions/11702477/binding-generic-types-in-ninject-3-0. В TypeExtensions.KetBindingDefintionOf() - одна опечатка - вы должны передать 'd' вместо 'definition' при создании BindingDefinition в методе Select. – Baldy

78

Это должно работать: -

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

где: -

IRepository <> является интерфейс вида: -

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

Repository <> класс формы: -

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

Я надеюсь, что это помогает :-)

+0

Как бы выглядел конструктор? – chobo2

+0

@ chobo2 смотреть оригинал сообщение? – Izmoto

+1

работает без «где T: класс»? – Boinst

0

Просто вопрос о вашем FindAndBindInterfaces метод: внутри Еогеаспа вы не имеете «закрытие» проблемы на intf переменная? Я все еще не уверен, что понял, как работает проблема закрытия.

Во всяком случае, на всякий случай, я думаю, что вы должны изменить свой Еогеасп в нечто вроде:

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

Если вы импортируете расширение конвенций Ninject, его GenericBindingGenerator должны быть в состоянии помочь вам. Он добавляет поддержку общих интерфейсов.

+2

Как это помогает? –

+0

Я обновил свой ответ. Он добавляет поддержку общих интерфейсов. – neontapir

Смежные вопросы