解析来自总线的命令
Resolve commands from Bus
目前不再处理命令同步,而是将它们放在消息总线上以便稍后处理,但在尝试加载命令而不是逐个输入命令时返回真实类型时遇到问题
这是我目前所拥有的并且似乎工作正常
命令调度程序
public class CommandDispatcher : ICommandDispatcher
{
private readonly IBus _commandBus;
public CommandDispatcher(IBus commandBus)
{
_commandBus = commandBus;
}
public void Dispatch<TCommand>(TCommand command) where TCommand : ICommand
{
var messageType = typeof(TCommand);
_commandBus.Publish(messageType, command);
}
正在订阅命令
bus.Subscribe<CommandOne>("key", HandleCommand);
bus.Subscribe<CommandTwo>("key", HandleCommand);
处理消息
private void HandleCommand<TCommand>(TCommand command) where TCommand : ICommand
{
var handler = _container.Resolve<ICommandHandler<TCommand>>();
handler.Handle(command);
}
我基本上想按照约定解决我的消息,所以这就是我想要的方向,所以我不必键入每个命令类型,但在取回类型时遇到问题
var commandAssembly = Assembly.GetAssembly(typeof(ICommand));
var commands = commandAssembly.GetTypes().Where(x => typeof(ICommand).IsAssignableFrom(x));
foreach (var command in commands)
{
bus.Subscribe(command, "key", x =>
{
HandleCommand(x);
});
}
现在 x 只是一个我无法传递给 Handlecommand 方法的对象
我为我的容器使用 autofac,为我的总线使用 easynetq。
我认为这部分:
private void HandleCommand<TCommand>(TCommand command) where TCommand : ICommand
{
var handler = _container.Resolve<ICommandHandler<TCommand>>();
handler.Handle(command);
}
都是AutoSubscriber为你做的,如果你实现IConsume<T>
而不是ICommandHandler<T>
,它们似乎有相同的目的。
https://github.com/EasyNetQ/EasyNetQ/wiki/Auto-Subscriber
您需要单独的 ICommandHandler<T>
界面有什么具体原因吗?
另一个注意事项:在您的实现中,您在解析命令处理程序时没有创建单独的 'scope',导致处理程序的每个实例(以及任何依赖项)永远存在于 'root' 范围。换句话说:内存泄漏 :)
如果你仍然想坚持你的实现,我认为最好这样做:
private void HandleCommand<TCommand>(TCommand command) where TCommand : ICommand
{
using(var scope = _container.BeginLifetimeScope("my-command-scope"))
{
var handler = scope.Resolve<ICommandHandler<TCommand>>();
handler.Handle(command);
}
}
但是,如果您使用 AutoSubscriber,这就是 AutofacMessageDispatcher 将为您做的事情:
目前不再处理命令同步,而是将它们放在消息总线上以便稍后处理,但在尝试加载命令而不是逐个输入命令时返回真实类型时遇到问题
这是我目前所拥有的并且似乎工作正常
命令调度程序
public class CommandDispatcher : ICommandDispatcher
{
private readonly IBus _commandBus;
public CommandDispatcher(IBus commandBus)
{
_commandBus = commandBus;
}
public void Dispatch<TCommand>(TCommand command) where TCommand : ICommand
{
var messageType = typeof(TCommand);
_commandBus.Publish(messageType, command);
}
正在订阅命令
bus.Subscribe<CommandOne>("key", HandleCommand);
bus.Subscribe<CommandTwo>("key", HandleCommand);
处理消息
private void HandleCommand<TCommand>(TCommand command) where TCommand : ICommand
{
var handler = _container.Resolve<ICommandHandler<TCommand>>();
handler.Handle(command);
}
我基本上想按照约定解决我的消息,所以这就是我想要的方向,所以我不必键入每个命令类型,但在取回类型时遇到问题
var commandAssembly = Assembly.GetAssembly(typeof(ICommand));
var commands = commandAssembly.GetTypes().Where(x => typeof(ICommand).IsAssignableFrom(x));
foreach (var command in commands)
{
bus.Subscribe(command, "key", x =>
{
HandleCommand(x);
});
}
现在 x 只是一个我无法传递给 Handlecommand 方法的对象
我为我的容器使用 autofac,为我的总线使用 easynetq。
我认为这部分:
private void HandleCommand<TCommand>(TCommand command) where TCommand : ICommand
{
var handler = _container.Resolve<ICommandHandler<TCommand>>();
handler.Handle(command);
}
都是AutoSubscriber为你做的,如果你实现IConsume<T>
而不是ICommandHandler<T>
,它们似乎有相同的目的。
https://github.com/EasyNetQ/EasyNetQ/wiki/Auto-Subscriber
您需要单独的 ICommandHandler<T>
界面有什么具体原因吗?
另一个注意事项:在您的实现中,您在解析命令处理程序时没有创建单独的 'scope',导致处理程序的每个实例(以及任何依赖项)永远存在于 'root' 范围。换句话说:内存泄漏 :)
如果你仍然想坚持你的实现,我认为最好这样做:
private void HandleCommand<TCommand>(TCommand command) where TCommand : ICommand
{
using(var scope = _container.BeginLifetimeScope("my-command-scope"))
{
var handler = scope.Resolve<ICommandHandler<TCommand>>();
handler.Handle(command);
}
}
但是,如果您使用 AutoSubscriber,这就是 AutofacMessageDispatcher 将为您做的事情: