配置MassTransit以反序列化多态属性

时间:2015-12-01 19:24:04

标签: c# serialization masstransit

因此,我们发送一个由复杂域类型组成的消息。我们的消费者没有触发,因为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属性的消息/域类或总线配置。任何能够成功通过上述测试方法的东西。

1 个答案:

答案 0 :(得分:2)

ITestMessage接口声明更改为:

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

为我解决了这个问题。