【发布时间】:2016-10-17 18:37:01
【问题描述】:
这个问题涉及事件(基类事件和子类事件)和事件处理程序。我正在处理现有代码,这似乎不像作者预期的那样工作。我很难理解为什么它不起作用,所以我想在尝试修复现有代码之前了解发生了什么。
我发现了以下问题,这可能暗示我需要为子类型事件创建额外的事件处理程序:
C#: Raising an inherited event
如果制作一个额外的事件处理程序确实是解决方案,我仍然想了解为什么会这样。这是我在这里的第一个问题,我确实试图寻找我的问题的答案/解释,但如果它仍然是我应该很容易找到的东西,我深表歉意。严厉的“RTFM!”在这一点上,有一个教育链接对我来说很好:)
我们有 2 个事件类,一个基类型和一个子类型。子类型事件的存在是为了处理删除事件。
public class BaseTypeEvent
{
public Guid Id { get; set; }
public string Name { get; set; }
public BaseTypeEvent()
{ }
public BaseTypeEvent(SomeRandomThing item)
{
Id = item.Id;
Name = item.Name;
}
}
public class SubTypeEvent : BaseTypeEvent
{
public DateTimeOffset Deleted { get; set; }
public SubTypeEvent()
{
Deleted = DateTimeOffset.UtcNow;
}
}
这些事件的用法似乎失败了:
public class UsageClass
{
public UsageClass(IEventBusService eventBusService)
{
eventBusService.MyBaseTypeEvents += HandleMethod;
}
private void HandleMethod(BaseTypeEvent e)
{
if(e is SubTypeEvent)
{
//code that deals with deletion events
//execution never actually gets here
}
//code that deals with events that are not deletion events
}
}
事件的声明在IEventBusService和EventBusService中:
public delegate void MyEventHandler(BaseTypeEvent e);
public interface IEventBusService
{
public event MyEventHandler MyBaseTypeEvents;
void PublishStuff(BaseTypeEvent e);
}
public class EventBusService : IEventBusService, IDisposable
{
public void Initialize()
{
//Bus is MassTransit
Bus.Initialize(sbc =>
{
sbc.Subscribe(subs => subs.Handler<BaseTypeEvent>(OnBaseTypeEvent));
}
}
private void OnBaseTypeEvent(BaseTypeEvent e)
{
if (MyBaseTypeEvents == null) return;
try
{
MyBaseTypeEvents(e);
}
catch (Exception e)
{
//some logging
}
}
public event MyEventHandler MyBaseTypeEvents;
public void PublishStuff(BaseTypeEvent e)
{
//some logging
//publish e to the event bus of our choice (MassTransit)
Bus.Instance.Publish(e);
}
}
最后是我们发送删除事件的地方(尝试删除我在上面巧妙地命名为 SomeRandomThing 的项目):
eventBusService.PublishStuff(new SubTypeEvent
{
Id = id,
Deleted = DateTimeOffset.UtcNow
});
所以问题是:在使用上面最后一行代码发送删除事件之后,UsageClass 中检查传入事件是否为 SubTypeEvent 类型的 if 语句实际上永远不会为真。 UsageClass的HandleMethod中e的类型是BaseTypeEvent。
编辑:
我决定在这种情况下摆脱子类型。我们现在不再有 BaseTypeEvent 和 SubTypeEvent,而只有 EventTypeA 和 EventTypeB。一个处理创建和更新,另一个处理删除(与创建和更新相比,我们需要的信息要少得多)。
public delegate void MyEventAHandler(EventTypeA e);
public delegate void MyEventBHandler(EventTypeB e);
和
void PublishStuffForA(EventTypeA e);
void PublishStuffForB(EventTypeB e);
等等。
我在 EventbusService 的 Initialize 方法中额外订阅了 MassTransit,并在需要它们的各种 UsageClasses 中创建了额外的处理程序:
sbc.Subscribe(subs => subs.Handler<EventTypeA>(OnEventTypeA));
sbc.Subscribe(subs => subs.Handler<EventTypeB>(OnEventTypeB));
和
public UsageClass(IEventBusService eventBusService)
{
eventBusService.MyEventTypeAEvents += HandleMethodForA;
eventBusService.MyEventTypeBEvents += HandleMethodForB;
}
等等。
我现在不再需要检查传入事件是否属于某种类型,我只需分别处理两种类型。也许是一个警察,但它有效。
我很犹豫是否将此作为我自己问题的答案,因为 @Glubus 的 cmets 以及 @Travis 的 cmets 回答了我的问题。仍然认为这个小编辑文章可能会让每个人都知道我做了什么作为解决方案:)
编辑 2:
有用的信息来源:
Derived types are not published to consumers in MassTransit
MassTransit message mis-typing
MassTransit: Message contracts, polymorphism and dynamic proxy objects
【问题讨论】:
-
那么事件是什么类型的呢?
-
@Glubus: BaseTypeEvent
-
在我看来,此时对象确实是 BaseTypeEvent,虽然它应该可以转换为 SubTypeEvent,但如果您尝试在 HandleMethod 中执行此
e as SubTypeEvent会发生什么? -
//publish e to the event bus of our choice这是什么意思?打电话给OnBaseTypeEvent? -
您将
BaseTypeEvent类型传递给 subscribe 方法,这意味着将发送给订阅者的任何对象都将转换为该类型。尝试将您的类定义更改为EventBusService<T> where T : BaseTypeEvent,并订阅T而不是BaseTypeEvent您也可以键入参数化Initialize 方法而不是您的类。
标签: c# events inheritance subclass masstransit