2013-11-22 49 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

相关问题