2013-11-22 100 views
4

我目前的註冊代碼:自動註冊一個通用接口的所有實現

Assembly web = Assembly.Load("MyAssembly"); 
types.AddRange(web.GetTypes()); 
//etc. 

foreach (var theInterface in types.Where(t => t.IsInterface)) 
{ 
    var assignableType = types.Where(t => theInterface.IsAssignableFrom(t) && t != theInterface); 
    foreach (var type in assignableType) 
    { 
     container.RegisterType(theInterface, type); 
    } 
} 

我的通用接口和它的實現:

public interface IDomainEventHandler<in T> 
{ 
    void Handle(T message); 
} 

public class DomainEventHandler1 : IDomainEventHandler<PhilTest1> 
{ 
    public void Handle(PhilTest1 message) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 

public class DomainEventHandler2 : IDomainEventHandler<PhilTest2> 
{ 
    public void Handle(PhilTest2 message) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 

public class DomainEventHandler3 : IDomainEventHandler<PhilTest2> 
{ 
    public void Handle(PhilTest2 message) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 

public class PhilTest1 
{ 

} 

public class PhilTest2 
{ 

} 

這裏是我將如何解決的簡化版本:

IEnumerable<IDomainEventHandler<PhilTest2>> listeners = Container.ResolveAll<IDomainEventHandler<PhilTest2>>(); 
IEnumerable<IDomainEventHandler<PhilTest1>> listeners2 = Container.ResolveAll<IDomainEventHandler<PhilTest1>>(); 

這不起作用 - 偵聽器和偵聽器2在解析後都是空的。這並非意外。

在溫莎,我可以做這樣的事情:

container.Register(AllTypes.FromAssemblyNamed("MyAssembly").BasedOn(typeof(IDomainEventHandler<>)).WithService.Base()); 

我怎麼會註冊IDomainEventHandler的所有實例團結?我寧願保留現有的註冊碼(如果可能的話)。

回答

5

有點痛苦,但我終於通過谷歌搜索和調試拼湊一起:

報名:

IEnumerable<Type> handlers = types.Where(t => IsAssignableToGenericType(t, typeof(IDomainEventHandler<>)) && !t.IsInterface); 

    foreach (var handler in handlers) 
    { 
     container.AddNewExtension<OpenGenericExtension>() 
        .Configure<IOpenGenericExtension>() 
        .RegisterClosedImpl(typeof (IDomainEventHandler<>), handler); 
    } 

IsAssignableToGenericType方法:

private static bool IsAssignableToGenericType(Type givenType, Type genericType) 
    { 
     var interfaceTypes = givenType.GetInterfaces(); 

     foreach (var it in interfaceTypes) 
     { 
      if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType) 
       return true; 
     } 

     if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType) 
      return true; 

     Type baseType = givenType.BaseType; 
     if (baseType == null) return false; 

     return IsAssignableToGenericType(baseType, genericType); 
    } 

和擴展。請注意,如果我沒有使用名稱進行註冊,則只會保留一種類型的註冊。我相信這是通過設計?

public interface IOpenGenericExtension : IUnityContainerExtensionConfigurator 
{ 
    void RegisterClosedImpl(Type openGenericInterface, Type closedType); 
} 

public class OpenGenericExtension : UnityContainerExtension, IOpenGenericExtension 
{ 
    protected override void Initialize() {} 

    public void RegisterClosedImpl(Type openGenericInterface, Type closedType) 
    { 
     closedType.GetInterfaces().Where(x => x.IsGenericType) 
        .Where(x => x.GetGenericTypeDefinition() == openGenericInterface) 
        .ToList() 
        .ForEach(x => Container.RegisterType(x, closedType, closedType.Name)); 
    } 
} 
+3

感謝您的支持。與其他IoC容器相比,我覺得Unity是貧血的。 – will

+0

幸好Unity現在通過'container.RegisterTypes'方法進行基於約定的註冊。這也適用於仿製藥! yey – MichaC

相關問題