gcs*_*cso 5 c# generics .net-3.5
我创建了一个非常简单的事件发布者,它看起来像这样.
public class EventPublisher
{
private readonly IList<Func<IHandle>> _subscribers;
public EventPublisher(IList<Func<IHandle>> subscribers)
{
_subscribers = subscribers;
}
public void Publish<TPayload>(TPayload payload)
where TPayload : class
{
var payloadHandlers = _subscribers.OfType<Func<IHandle<TPayload>>>();
foreach (var payloadHandler in payloadHandlers)
{
payloadHandler().Handle(payload);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我发布消息的方法.
var subscribers = new List<Func<IHandle>> {() => new SomeHandler()};
var eventPublisher = new EventPublisher(subscribers);
eventPublisher.Publish(new SomeMessage { Text = "Some random text..." });
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是发布消息并没有找到任何可以处理有效负载的处理程序.这是有道理的,因为我注册了我的订阅者Func<IHandle>而不是Func<IHandle<T>>.
继承自我的处理程序类的接口来自Caliburn.Micro.EventAggregator,它看起来像这样.
public interface IHandle {}
public interface IHandle<TMessage> : IHandle {
void Handle(TMessage message);
}
Run Code Online (Sandbox Code Playgroud)
什么是必须的类型_subscribers是处理IHandle<>在泛型类型可以是任何具体类型?
假设您使用的是 .NET 4,我希望它能工作:
var subscribers = new List<Func<IHandle<SomeMessage>>> {() => new SomeHandler()};
Run Code Online (Sandbox Code Playgroud)
然后得到协方差:
public EventPublisher(IEnumerable<Func<IHandle>> subscribers)
{
_subscribers = subscribers.ToList();
}
Run Code Online (Sandbox Code Playgroud)
这使您可以订阅与Func<IHandle>. 请注意,它确实显着改变了语义,因为订阅者集将在构造后固定。就我个人而言,我认为这是一件好事,但它可能不适合你。
或者,它EventPublisher本身是否必须与多种类型一起工作?你能制作它EventPublisher<T>并IHandle<T>在任何地方使用,使其成为Publish非通用的吗?根据您想要如何使用它,这可能可行也可能不可行 - 两个选项都有意义。