簡體   English   中英

配置MassTransit以反序列化多態屬性

[英]Configure MassTransit to deserialize polymorphic properties

因此,我們正在發送由復雜域類型組成的消息。 我們的消費者沒有觸發,因為MassTransit無法反序列化消息並委托給消費者。

這種情況可以通過以下方式演示

// message interface
public interface ITestMessage { TestBaseClass Data { get; set; } };

// message implementation
public class TestMessage : ITestMessage
{
    public TestBaseClass Data { get; set; }
}

// abstract child
public abstract class TestBaseClass { }

// a concrete implementation of abstract child, cannot be deserialized 
// by default serializer configuration
public class TestConcreteClass : TestBaseClass { }

// simple consumer, uses a reset-event to synchronize with calling
// test method
public class TestConsumer : IConsumer<ITestMessage>
{
    private readonly Action action = null;
    public TestConsumer(Action action) { this.action = action; }
    public Task Consume(ConsumeContext<ITestMessage> context)
    {
        action();
        return context.CompleteTask;
    }
}

[TestMethod]
public void Publish_WhenPolymorphicMessage_ConsumesMessage()
{
    ManualResetEvent isConsumed = new ManualResetEvent(false);
    IBusControl bus = Bus.Factory.CreateUsingInMemory(c =>
    {
        InMemoryTransportCache inMemoryTransportCache = 
            new InMemoryTransportCache(Environment.ProcessorCount);
        c.SetTransportProvider(inMemoryTransportCache);
        c.ReceiveEndpoint(
            "", 
            e => e.Consumer<TestConsumer>(
                () => new TestConsumer(() => isConsumed.Set())));
    });
    bus.Start();

    ITestMessage message = new TestMessage 
    {
        // comment out assignment below, et voila, we pass :S
        Data = new TestConcreteClass { },
    };

    // attempt to publish message and wait for consumer
    bus.Publish<ITestMessage>(message);

    // simple timeout fails
    Assert.IsTrue(isConsumed.WaitOne(TimeSpan.FromSeconds(5)));
}

當然,我們可以成功地證明帶有多態子項的消息可以序列化

[TestMethod]
public void Serialize_WithPolymorphicChild_DeserializesCorrectly()
{
    ITestMessage message = new TestMessage { Data = new TestConcreteClass { }, };
    JsonSerializerSettings settings = 
        new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All, };
    string messageString = JsonConvert.SerializeObject(message, settings);
    ITestMessage messageDeserialized = (ITestMessage)(JsonConvert.DeserializeObject(
        messageString, 
        settings));

    Assert.IsNotNull(messageDeserialized);
    Assert.IsNotNull(messageDeserialized.Data);
    Assert.IsInstanceOfType(messageDeserialized.Data, typeof(TestConcreteClass));
    Assert.AreNotSame(message.Data, messageDeserialized.Data);
}

我嘗試了各種配置,但無濟於事。

IBusControl bus = Bus.Factory.CreateUsingInMemory(c =>
{
    InMemoryTransportCache inMemoryTransportCache = 
        new InMemoryTransportCache(Environment.ProcessorCount);
    c.SetTransportProvider(inMemoryTransportCache);

    // attempt to set and configure json serializer; zero effect
    c.ConfigureJsonDeserializer(
        s => 
        {
            s.TypeNameHandling = TypeNameHandling.All; 
            return s;
        });
    c.ConfigureJsonSerializer(
        s => 
        {
            s.TypeNameHandling = TypeNameHandling.All; 
            return s; 
        });
    c.UseJsonSerializer();

    c.ReceiveEndpoint(
        "", 
        e => e.Consumer<TestConsumer>(
            () => new TestConsumer(() => isConsumed.Set())));
});

我正在尋找任何成功的解決方案,例如裝飾帶有KnownType屬性的消息/域類或總線配置。 任何導致上述測試方法成功通過的因素。

將您的ITestMessage接口聲明更改為:

// message interface
public interface ITestMessage
{
    [JsonProperty(TypeNameHandling = TypeNameHandling.Objects)]
    TestBaseClass Data { get; set; }
};

為我解決了這個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM