C# 使用Autofac的单一消息处理程序工厂

C# 使用Autofac的单一消息处理程序工厂,c#,dependency-injection,autofac,C#,Dependency Injection,Autofac,因此,我有一个名为IMessage的标记接口。然后我有如下类: public class MessageA: IMessage { } 然后我将消息处理程序定义为: internal interface IMessageHandler<in T> where T: IMessage { void Handle(T message); } public class MessageAHandler : IMessageHandler<MessageA> {

因此,我有一个名为
IMessage
的标记接口。然后我有如下类:

public class MessageA: IMessage 
{
}
然后我将消息处理程序定义为:

internal interface IMessageHandler<in T> where T: IMessage
{
    void Handle(T message);
}

public class MessageAHandler : IMessageHandler<MessageA> 
{
    public void Handle(T message)
    { 
        //Some logic here
    }
}
我现在可以通过使用下面这样的工厂来实现这一点,但我需要对每一个工厂都有依赖关系,并根据不同类型的消息创建一个新工厂。因此,我想知道是否有一种方法可以创建一个足够智能的工厂来解析适当的消息处理程序

public class MessageReceiver
{
   private readonly Func<IMessageHandler<MessageA>> _messageAFactory;

   public MessageReceiver(Func<IMessageHandler<MessageA>> messageAFactory)
   {
       _messageAFactory= messageAFactory;
   }

   public void ReceiveMessage(IMessage message)
   {
       if (message is MessageA)
       {
           var messageHandler = _messageAFactory();
           messageHandler.Handle(message as MessageA);
       }

       // Add more if-statements here for more messages
   }
}
公共类MessageReceiver
{
私有只读函数库;
公共消息接收者(Func messageAFactory)
{
_messageAFactory=messageAFactory;
}
公共无效接收消息(IMessage消息)
{
如果(消息是MessageA)
{
var messageHandler=_messageAFactory();
Handle(消息作为MessageA);
}
//在此处添加更多if语句以获取更多消息
}
}

自动传真注册

public class InfrastructureModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        //Register the types in the infrastructure assembly
        builder.RegisterAssemblyTypes(ThisAssembly).AsImplementedInterfaces()
            .InstancePerLifetimeScope();

        //Register the message handlers
        builder.RegisterAssemblyTypes(ThisAssembly)
        .Where(x => x.IsAssignableFrom(typeof(IMessageHandler<IMessage>)))
        .InstancePerDependency().AsImplementedInterfaces();
    }
}
公共类基础设施模块:模块
{
受保护的覆盖无效负载(ContainerBuilder builder)
{
//在基础结构程序集中注册类型
RegisterAssemblyTypes(ThisAssembly.AsImplementedInterfaces())
.InstancePerLifetimeScope();
//注册消息处理程序
builder.RegisterAssemblyTypes(此程序集)
.Where(x=>x.IsAssignableFrom(typeof(IMessageHandler)))
.InstancePerDependency().AsImplementedInterface();
}
}

首先,我将为您的消息制作一个小的实现,只是一个基本的handled标志,以便进行测试

public class MessageA : IMessage
{
    public bool Handled
    {
        get;
        private set;
    }

    public void MarkAsHandled()
    {
        this.Handled = true;
    }
}

public class MessageB : IMessage
{
    public bool Handled
    {
        get;
        private set;
    }

    public void MarkAsHandled()
    {
        this.Handled = true;
    }
}
现在,让我们将这两个处理程序实现为:

public class MessageAHandler : IMessageHandler<MessageA>
{
    public void Handle(MessageA message)
    {
        message.MarkAsHandled();
    }
}

public class MessageBHandler : IMessageHandler<MessageB>
{
    public void Handle(MessageB message)
    {
        message.MarkAsHandled();
    }
}
public类MessageAHandler:IMessageHandler
{
公共无效句柄(MessageA消息)
{
message.MarkAsHandled();
}
}
公共类MessageBHandler:IMessageHandler
{
公共无效句柄(MessageB消息)
{
message.MarkAsHandled();
}
}
作为旁注,您可能希望将IMessageHandler接口标记为public(如果可见性设置为internal,则会出现编译器错误)

现在,让我们添加一个小处理程序:

public interface IMessageHandler
{
    Type MessageType { get; }
    void Handle(IMessage message);
}

public class MessageHandlerAdapter<T> : IMessageHandler where T : IMessage
{
    private readonly Func<IMessageHandler<T>> handlerFactory;

    public MessageHandlerAdapter(Func<IMessageHandler<T>> handlerFactory)
    {
        this.handlerFactory = handlerFactory;
    }

    public void Handle(IMessage message)
    {
        var handler = handlerFactory();
        handler.Handle((T)message);
    }

    public Type MessageType
    {
        get { return typeof(T); }
    }
}
公共接口IMessageHandler
{
类型MessageType{get;}
无效句柄(IMessage消息);
}
公共类MessageHandlerAdapter:IMessageHandler,其中T:IMessage
{
私有只读Func handlerFactory;
公共消息HandlerAdapter(Func handlerFactory)
{
this.handlerFactory=handlerFactory;
}
公共无效句柄(IMessage消息)
{
var handler=handlerFactory();
handler.Handle((T)消息);
}
公共类型MessageType
{
获取{return typeof(T);}
}
}
我们现在可以通过以下方式实现MessageReceiver:

public class MessageReceiver
{
    private readonly IEnumerable<IMessageHandler> handlers;

    public MessageReceiver(IEnumerable<IMessageHandler> handlers)
    {
        this.handlers = handlers;
    }

    public void ReceiveMessage(IMessage message)
    {
        var handler = this.handlers.Where(h => h.MessageType == message.GetType()).FirstOrDefault();

        if (handler != null)
        {
            handler.Handle(message);
        }
        else
        {
            //Do something here, no handler found for message type
        }
    }
}
公共类MessageReceiver
{
私有只读IEnumerable处理程序;
public MessageReceiver(IEnumerable处理程序)
{
this.handlers=handlers;
}
公共无效接收消息(IMessage消息)
{
var handler=this.handlers.Where(h=>h.MessageType==message.GetType()).FirstOrDefault();
if(处理程序!=null)
{
handler.Handle(消息);
}
其他的
{
//在此处执行操作,未找到消息类型的处理程序
}
}
}
现在,为了测试我们的消息是否得到了正确处理,下面是一个小测试:

[TestClass]
public class TestSelector
{
    private IContainer container;

    [TestMethod]
    public void TestMethod()
    {
        var processor = container.Resolve<MessageReceiver>();

        MessageA ma = new MessageA();
        MessageB mb = new MessageB();

        processor.ReceiveMessage(ma);
        processor.ReceiveMessage(mb);

        Assert.AreEqual(ma.Handled, true);
        Assert.AreEqual(mb.Handled, true);

    }
}
[TestClass]
公共类测试选择器
{
私人集装箱;
[测试方法]
公共void TestMethod()
{
var processor=container.Resolve();
MessageA ma=新MessageA();
MessageB mb=newmessageb();
处理器。接收消息(ma);
处理器。接收消息(mb);
Assert.AreEqual(ma.Handled,true);
aresequal(mb.Handled,true);
}
}
我们需要对注册进行一些修改,如果选择手动注册,我们将执行以下操作:

    public TestSelector()
    {
        var containerBuilder = new ContainerBuilder();

        containerBuilder.RegisterType<MessageAHandler>().As<IMessageHandler<MessageA>>();
        containerBuilder.RegisterType<MessageBHandler>().As<IMessageHandler<MessageB>>();

        containerBuilder.RegisterType<MessageHandlerAdapter<MessageA>>().As<IMessageHandler>();
        containerBuilder.RegisterType<MessageHandlerAdapter<MessageB>>().As<IMessageHandler>();

        containerBuilder.RegisterType<MessageReceiver>();

        this.container = containerBuilder.Build();
    }
publictestselector()
{
var containerBuilder=新的containerBuilder();
containerBuilder.RegisterType().As();
containerBuilder.RegisterType().As();
containerBuilder.RegisterType().As();
containerBuilder.RegisterType().As();
containerBuilder.RegisterType();
this.container=containerBuilder.Build();
}
在这里,我们现在需要注册一个处理程序和相关适配器

当然也可以执行部件扫描,但这需要更多的管道,因为使用:

builder.RegisterAssemblyTypes(ThisAssembly)
    .Where(x => x.IsAssignableFrom(typeof(IMessageHandler<IMessage>)))
    .InstancePerDependency().AsImplementedInterfaces();
builder.RegisterAssemblyTypes(此程序集)
.Where(x=>x.IsAssignableFrom(typeof(IMessageHandler)))
.InstancePerDependency().AsImplementedInterface();
行不通

typeof(MessageAHandler).IsAssignableFrom(typeof(IMessageHandler<IMessage>))
typeof(MessageAHandler).IsAssignableFrom(typeof(IMessageHandler))
将返回false,因为MessageAHandler实现的是IMessageHandler,而不是IMessageHandler

要执行自动查找和注册,请执行以下代码片段:

    public TestSelector()
    {
        var containerBuilder = new ContainerBuilder();

        Func<Type, Type> GetHandlerInterface = (t) => t.GetInterfaces()
            .Where(iface => iface.IsGenericType && iface.GetGenericTypeDefinition() == typeof(IMessageHandler<>)).FirstOrDefault();

        var handlerTypes = typeof(IMessage).Assembly.GetTypes()
            .Where(type => type.IsClass
                && !type.IsAbstract
                && GetHandlerInterface(type) != null);

        foreach (Type handlerType in handlerTypes)
        {
            Type messageType = GetHandlerInterface(handlerType).GetGenericArguments()[0];
            var genericHandler = typeof(MessageHandlerAdapter<>).MakeGenericType(messageType);

            containerBuilder.RegisterType(handlerType).AsImplementedInterfaces();
            containerBuilder.RegisterType(genericHandler).As<IMessageHandler>();
        }

        containerBuilder.RegisterType<MessageReceiver>();

        this.container = containerBuilder.Build();
    }
publictestselector()
{
var containerBuilder=新的containerBuilder();
Func GetHandlerInterface=(t)=>t.GetInterfaces()
.Where(iface=>iface.IsGenericType&&iface.GetGenericTypeDefinition()==typeof(IMessageHandler)).FirstOrDefault();
var handlerTypes=typeof(IMessage).Assembly.GetTypes()
.Where(type=>type.IsClass
&&!type.IsAbstract
&&GetHandlerInterface(类型)!=null);
foreach(handlerType中的类型handlerType)
{
类型messageType=GetHandlerInterface(handlerType).GetGenericArguments()[0];
var genericHandler=typeof(MessageHandlerAdapter)。MakeGenericType(messageType);
containerBuilder.RegisterType(handlerType).AsImplementedInterfaces();
RegisterType(genericHandler.As();
}
containerBuilder.RegisterType();
this.container=containerBuilder.Build();
}

对于仍在寻找更好的自动分派到已注册的相应消息处理程序的解决方案的任何人
    public TestSelector()
    {
        var containerBuilder = new ContainerBuilder();

        Func<Type, Type> GetHandlerInterface = (t) => t.GetInterfaces()
            .Where(iface => iface.IsGenericType && iface.GetGenericTypeDefinition() == typeof(IMessageHandler<>)).FirstOrDefault();

        var handlerTypes = typeof(IMessage).Assembly.GetTypes()
            .Where(type => type.IsClass
                && !type.IsAbstract
                && GetHandlerInterface(type) != null);

        foreach (Type handlerType in handlerTypes)
        {
            Type messageType = GetHandlerInterface(handlerType).GetGenericArguments()[0];
            var genericHandler = typeof(MessageHandlerAdapter<>).MakeGenericType(messageType);

            containerBuilder.RegisterType(handlerType).AsImplementedInterfaces();
            containerBuilder.RegisterType(genericHandler).As<IMessageHandler>();
        }

        containerBuilder.RegisterType<MessageReceiver>();

        this.container = containerBuilder.Build();
    }