MassTransit消息使用者永远不会看到子类类型

use*_*667 5 c# events inheritance subclass masstransit

这个问题涉及事件(基类事件和子类事件)和事件处理程序.我正在研究现有的代码,这似乎不像作者所期望的那样工作.我很难理解为什么它不起作用,所以我想了解在我尝试修复现有代码之前发生了什么.

我发现了以下问题,可能会或可能不会建议我需要为子类型事件创建一个额外的事件处理程序:

C#:提升继承的事件

如果制作一个额外的事件处理程序确实是解决方案,我仍然想知道为什么会这样.这是我的第一个问题,我确实试着在我的问题中寻找答案/解释,但真诚的道歉,如果它仍然是我应该很容易找到的东西.严厉的"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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这些事件的使用似乎失败了:

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
     }
}
Run Code Online (Sandbox Code Playgroud)

事件的声明在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

最后是我们发送删除事件的地方(试图删除我上面巧妙地命名为SomeRandomThing的项目):

eventBusService.PublishStuff(new SubTypeEvent
    {
        Id = id,
        Deleted = DateTimeOffset.UtcNow
    });
Run Code Online (Sandbox Code Playgroud)

所以问题是:在使用上面的最后一行代码发送删除事件之后,UsageClass中的if语句检查传入事件是否为SubTypeEvent类型,实际上从未实现.UsageClass的HandleMethod中的e类型是BaseTypeEvent.

编辑:

在这种情况下,我决定摆脱子类型.我们现在不再拥有BaseTypeEvent和SubTypeEvent,而只是EventTypeA和EventTypeB.一个处理创建和更新,另一个处理删除(我们需要创建和更新的信息少得多).

public delegate void MyEventAHandler(EventTypeA e);
public delegate void MyEventBHandler(EventTypeB e);
Run Code Online (Sandbox Code Playgroud)

void PublishStuffForA(EventTypeA e);
void PublishStuffForB(EventTypeB e);
Run Code Online (Sandbox Code Playgroud)

等等.

我在EventbusService的Initialize方法中额外订阅了MassTransit,并在需要它们的各种UsageClasses中添加了额外的处理程序:

sbc.Subscribe(subs => subs.Handler<EventTypeA>(OnEventTypeA));
sbc.Subscribe(subs => subs.Handler<EventTypeB>(OnEventTypeB));
Run Code Online (Sandbox Code Playgroud)

public UsageClass(IEventBusService eventBusService)
{
    eventBusService.MyEventTypeAEvents += HandleMethodForA;
    eventBusService.MyEventTypeBEvents += HandleMethodForB;
}
Run Code Online (Sandbox Code Playgroud)

等等.

我现在不再需要检查传入的事件是否属于某种类型,我只是分别处理两种类型.也许是一个警察,但它的工作原理.

由于@Glubus的评论和@Travis的评论都回答了我的问题,我对于将此作为我自己问题的答案犹豫不决.仍然认为这个小编辑可能很高兴让每个人都知道我做了什么作为解决方案:)

编辑2:

有用的信息来源:

派生类型不会在MassTransit中发布给消费者

MassTransit消息错误输入

MassTransit:消息契约,多态和动态代理对象

https://groups.google.com/forum/#!searchin/masstransit-discuss/polymorphism/masstransit-discuss/q_M4erHQ7OI/FxaotfIzI7YJ

Tra*_*vis 2

所以我可以告诉你简短的答案:

在消息传递合约中使用多态性会引入耦合。

作为大众交通开发商,我们认为这是一个坏主意。这仍然是可能的,但不是开箱即用的。您必须使用二进制序列化或客户序列化程序。默认情况下,序列化管道仅填充使用者中该类型的代理。