我当前的注册代码:
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>>();
这不起作用——解析后listeners和listeners2都为空。这并不意外。
在温莎,我可以做这样的事情:
container.Register(AllTypes.FromAssemblyNamed("MyAssembly").BasedOn(typeof(IDomainEventHandler<>)).WithService.Base());
如何在Unity中注册IDomainEventHandler的所有实例?我更愿意保留现有的注册代码(如果可能的话)。
有点痛苦,但我最终通过谷歌和调试拼凑起来:
注册:
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));
}
}