带有 IoC 的事件调度库
Event dispatching library with IoC
过去,我构建了一个 MessageDispatcher
组件,该组件扫描程序集以查找装饰有特定属性的类型并初始化每个类型的实例。然后,当任何对象被提供给 MessageDispatcher
实例时,每个先前初始化的实例都包含一个方法,该方法的签名包含所传递对象的类型,并使用指定的参数触发该方法。例如,在这样的场景中:
[Listener]
public class MyListener
{
MessageDispatcher _dispatcher; //Assigned elsewhere
[MessageListener]
public async Task DoSomething(int value)
{
var otherValue = await _dispatcher.Next<string>();
Console.WriteLine($"{value} is {otherValue}.");
}
}
以下代码初始化 MyListener
class 的一个实例,调用 DoSomething
并打印“7 is okay”:
var listener = new MessageDispatcher(typeof (ListenerAttribute));
listener.Dispatch(7);
listener.Dispatch("okay");
我想知道 是否有任何图书馆专门提供或包含此类服务 。它必须能够:
- 扫描程序集并根据属性初始化类型。
- 动态地 "subscribe" 某些类型
- "Wait" 从调度程序中提取的值(就像我示例中的
Next
方法)。
(因为 SO 规则不允许库推荐,这里尝试用一个实现来代替回答)
几乎任何 IoC 都可以做到这一点。他们所需要的只是能够使用属性或其他一些常规方式注册服务。
至于消息发送。只需创建一个像 IMessageHandler<TMessage>
这样的界面。在所有应该处理消息的 class 上实现它。
示例:
public interface IMessageHandler<TMessage>
{
void Handle(TMessage msg);
}
public class SomeService : IMessageHandler<UserCreated>
{
//[.. all other methods ..]
public void Handle(UserCreated msg)
{
// ...
}
}
要发布消息,您需要创建一个调度程序。由于您使用容器,因此不必将其设为静态。使用其中的容器(服务位置)来发送消息。现在有些人可能会说 oohh 不,服务位置是反模式,buhuhuhu。好吧,不。并非在所有情况下。在这种情况下,它是 class 中的一个实现细节,具有识别和调用其他 classes 的特定目的。
public interface IMessageDispatcher
{
void Dispatch<TMessage>(TMessage msg);
}
// The actual implementation differs
// depending on your choice of container.
public class ContainerBasedMessageDispatcher : IMessageDispatcher
{
Container _container;
public ContainerBasedMessageDispatcher(Container container)
{
_container = container;
}
public void Dispatch<TMessage>(TMessage message)
{
using (var scope = container.BeginLifetimeScope())
{
var handlers = scope.Resolve<IEnumerable<IMessageHandler<TMessage>>();
foreach (var handler in handlers)
{
handler.Handle(message);
}
}
}
}
代码是直接用SO写的。所以它可能无法按原样工作。但希望它能让您了解如何实现您想要的。
用法:
public class UserService
{
IMessageDispatcher _dispatcher;
public UserService(IMessageDispatcher dispatcher)
{
_dispatcher = dispatcher;
}
public void Create(User user)
{
//[...]
_dispatcher.Dispatch(new UserCreated(user.Id));
}
}
但是,这不会动态地允许您订阅您想要的内容。如果只是忽略不需要的消息是不可行的。那么这个答案不适合你。
过去,我构建了一个 MessageDispatcher
组件,该组件扫描程序集以查找装饰有特定属性的类型并初始化每个类型的实例。然后,当任何对象被提供给 MessageDispatcher
实例时,每个先前初始化的实例都包含一个方法,该方法的签名包含所传递对象的类型,并使用指定的参数触发该方法。例如,在这样的场景中:
[Listener]
public class MyListener
{
MessageDispatcher _dispatcher; //Assigned elsewhere
[MessageListener]
public async Task DoSomething(int value)
{
var otherValue = await _dispatcher.Next<string>();
Console.WriteLine($"{value} is {otherValue}.");
}
}
以下代码初始化 MyListener
class 的一个实例,调用 DoSomething
并打印“7 is okay”:
var listener = new MessageDispatcher(typeof (ListenerAttribute));
listener.Dispatch(7);
listener.Dispatch("okay");
我想知道 是否有任何图书馆专门提供或包含此类服务 。它必须能够:
- 扫描程序集并根据属性初始化类型。
- 动态地 "subscribe" 某些类型
- "Wait" 从调度程序中提取的值(就像我示例中的
Next
方法)。
(因为 SO 规则不允许库推荐,这里尝试用一个实现来代替回答)
几乎任何 IoC 都可以做到这一点。他们所需要的只是能够使用属性或其他一些常规方式注册服务。
至于消息发送。只需创建一个像 IMessageHandler<TMessage>
这样的界面。在所有应该处理消息的 class 上实现它。
示例:
public interface IMessageHandler<TMessage>
{
void Handle(TMessage msg);
}
public class SomeService : IMessageHandler<UserCreated>
{
//[.. all other methods ..]
public void Handle(UserCreated msg)
{
// ...
}
}
要发布消息,您需要创建一个调度程序。由于您使用容器,因此不必将其设为静态。使用其中的容器(服务位置)来发送消息。现在有些人可能会说 oohh 不,服务位置是反模式,buhuhuhu。好吧,不。并非在所有情况下。在这种情况下,它是 class 中的一个实现细节,具有识别和调用其他 classes 的特定目的。
public interface IMessageDispatcher
{
void Dispatch<TMessage>(TMessage msg);
}
// The actual implementation differs
// depending on your choice of container.
public class ContainerBasedMessageDispatcher : IMessageDispatcher
{
Container _container;
public ContainerBasedMessageDispatcher(Container container)
{
_container = container;
}
public void Dispatch<TMessage>(TMessage message)
{
using (var scope = container.BeginLifetimeScope())
{
var handlers = scope.Resolve<IEnumerable<IMessageHandler<TMessage>>();
foreach (var handler in handlers)
{
handler.Handle(message);
}
}
}
}
代码是直接用SO写的。所以它可能无法按原样工作。但希望它能让您了解如何实现您想要的。
用法:
public class UserService
{
IMessageDispatcher _dispatcher;
public UserService(IMessageDispatcher dispatcher)
{
_dispatcher = dispatcher;
}
public void Create(User user)
{
//[...]
_dispatcher.Dispatch(new UserCreated(user.Id));
}
}
但是,这不会动态地允许您订阅您想要的内容。如果只是忽略不需要的消息是不可行的。那么这个答案不适合你。