配置 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())));
});
我正在寻求任何 成功的解决方案,例如message/domain 类 具有KnownType
属性的修饰,或总线配置。导致成功通过上述测试方法的任何事情。
将您的 ITestMessage
接口声明更改为:
// message interface
public interface ITestMessage
{
[JsonProperty(TypeNameHandling = TypeNameHandling.Objects)]
TestBaseClass Data { get; set; }
};
为我解决了这个问题。
因此,我们正在发送由复杂域类型组成的消息。我们的消费者没有触发,因为 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())));
});
我正在寻求任何 成功的解决方案,例如message/domain 类 具有KnownType
属性的修饰,或总线配置。导致成功通过上述测试方法的任何事情。
将您的 ITestMessage
接口声明更改为:
// message interface
public interface ITestMessage
{
[JsonProperty(TypeNameHandling = TypeNameHandling.Objects)]
TestBaseClass Data { get; set; }
};
为我解决了这个问题。