简体   繁体   English

自动注册通用接口的所有实现

[英]Automatically Registering All Implementations of a Generic Interface

My current registration code: 我目前的注册码:

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

My generic interface and its implementations: 我的通用接口及其实现:

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
{

}

Here is a simplified version of how I would resolve: 这是我将如何解决的简化版本:

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

This doesn't work--listeners and listeners2 are both empty after resolving. 这不起作用 - 解析后侦听器和侦听器2都是空的。 This is not unexpected. 这并不意外。

In Windsor, I could do something like this: 在温莎,我可以这样做:

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

How would I register all instances of IDomainEventHandler in Unity? 我如何在Unity中注册IDomainEventHandler的所有实例? I'd prefer to keep the existing registration code intact (if possible). 我宁愿保持现有的注册码(如果可能的话)。

A bit painful, but I finally pieced it together via googling and debugging: 有点痛苦,但我最终通过谷歌搜索和调试将它拼凑在一起:

Registration: 注册:

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

And the Extension. 和扩展。 Note that if I didn't use a name for the registration, only one type would remain registered. 请注意,如果我没有使用名称进行注册,则只会注册一种类型。 I believe this is by design? 我相信这是设计的?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 获取通用接口的所有实现类型 - Get all implementations types of a generic interface 如何在autofac中注册Generic接口的所有实现? - How to register all implementations of Generic interface in autofac? .NET - 获取通用接口的所有实现? - .NET - Getting all implementations of a generic interface? 统一通用接口的实现 - Unify the implementations of a generic interface 在Castle Windsor中,如何为所有找到的通用类型的实现注册通用接口的许多实现之一? - In Castle Windsor, how to register ONE of many implementations of generic interface for ALL found implementations of generic type? 如何为使用MSpec的接口的所有实现编写通用测试? - How do I write generic tests for all implementations of an interface with MSpec? 使用structuremap获取和/或弹出通用接口的所有实现 - Getting and/or ejecting all implementations of a generic interface using structuremap 向Unity注册通用处理程序接口 - Registering Generic Handler Interface with Unity 我是否可以使用StructureMap返回特定类型参数的通用接口的所有实现 - Can I use StructureMap to return all implementations of a generic interface for a specific type parameter 从方法返回通用接口和子实现 - Returning generic interface and child implementations from a method
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM