通用命令处理程序的简单注入器用法 [英] Simple Injector usage for generic command handler

查看:78
本文介绍了通用命令处理程序的简单注入器用法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

按照Simpleinjector Wiki中的说明设置接口,命令和命令处理程序。

The interfaces,commands and command handler set up as per instructions in Simpleinjector wiki.

public interface ICommand
{
    string Name { get; set; }
}

public class Command1 : ICommand
{
    public string Name { get; set; }
}

public class Command2 : ICommand
{
    public string Name { get; set; }
}

public interface ICommandHandler<TCommand>
{
    void Execute(TCommand Command);
}

public class Command1Handler : ICommandHandler<Command1>
{
    public void Execute(Command1 Command) {
        Console.WriteLine(Command.Name);
    }
}

public class Command2Handler : ICommandHandler<Command2>
{
    public void Execute(Command2 Command) {
        Console.WriteLine(Command.Name + "Hello");
    }
}

装饰器:

public class CommandDecorator<TCommand> : ICommandHandler<TCommand>
{
    private readonly ICommandHandler<TCommand> _handler;

    public CommandDecorator(ICommandHandler<TCommand> handler)
    {
        this._handler = handler;
    }

    public void Execute(TCommand command)
    {
        this._handler.Execute(command);
    }
}

示例程序

public class Program
{
    static void Main(string[] args)
    {
        Container container = new Container();

        //registering 
        container.RegisterAll<ICommand>(typeof(Command1), typeof(Command2));

        container.RegisterManyForOpenGeneric(
            typeof(ICommandHandler<>),
            typeof(ICommandHandler<>).Assembly);

        container.RegisterDecorator(typeof(ICommandHandler<>), 
            typeof(CommandDecorator<>));

        container.Verify();

        // sample test command 
        ICommand testcommand = new Command2();
        testcommand.Name = "command 1";

        var type = typeof(ICommandHandler<>).MakeGenericType(testcommand.GetType());

        dynamic instance = container.GetInstance(type);
        instance.Execute((dynamic)testcommand);
    }
}

这是获取正确处理程序的正确方法吗在运行时处理命令。
这是一个示例,在实际的应用程序中,命令将发布到队列中,服务将读取命令并对其进行处理。
我想装饰器必须用于此功能,但无法使其正常工作。
请提出更好的选择。

Is this the right way to get the right handler for handling the command at runtime. This is a sample and in the real app the commands are going to posted to a queue and a service is going to read the command and process it . I guess the Decorator has to be used for that but am not able to get it working. please suggest better options if any.

推荐答案

您的命令( Command1 Command2 )不是服务:不应注册。它们是您通过服务(命令处理程序)传递的运行时数据(消息)。因此,您应该删除 Collection.Register< ICommand> (在v2中为 RegisterAll )注册。这是没有用的。您已经看到它没有用了,因为在您的示例中,您正在手动新建 Command2 ,这是正确的做法。

Your commands (Command1 and Command2) are not services: they should not be registered. They are runtime data (message) that you pass through your services (your command handlers). So you should remove the Collection.Register<ICommand> (RegisterAll in v2) registration. It is of no use. You already see its of no use, since in your example you are newing the Command2 up manually, which is the right thing to do.

在最后三行代码中,您正在执行的操作是向正确的命令处理程序注册分派未知类型的命令。由于需要根据命令类型构建封闭的 ICommandHandler< TCommand> 类型,因此始终需要一些思考来实现这一点,这是您不知道的编译时间。除了使用C# dynamic 关键字,还可以使用.NET反射API,但以我的经验使用 dynamic 在这种情况下更好。反射API的一个重要缺点是,该API始终会使用 InvocationException 包装任何抛出的异常(在失败的情况下),这使得执行某些异常处理变得更加困难

What you are doing in the last three lines of code is dispatching a command of an unknown type to the right command handler registration. You always need some reflection to pull this of, since you need to build the closed ICommandHandler<TCommand> type based on the command type, which is something you don't know at compile time. Instead of using the C# dynamic keyword, you can also use the .NET reflection API, but in my experience using dynamic is better in this particular case. One important downside of the reflection API is that the API will always wrap any thrown exception (in case of a failure) with an InvocationException and that makes it harder to do certain exception handling up the call stack.

长话短说,这应该是您的注册:

So long story short, this should be your registration:

Container container = new Container();

container.Register(
    typeof(ICommandHandler<>),
    typeof(ICommandHandler<>).Assembly);

container.RegisterDecorator(
    typeof(ICommandHandler<>), 
    typeof(CommandDecorator<>));

这应该是调度逻辑:

var type = typeof(ICommandHandler<>).MakeGenericType(command.GetType());

dynamic handler = container.GetInstance(type);
handler.Execute((dynamic)command);

这篇关于通用命令处理程序的简单注入器用法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆