为什么MassTransit使用ConstructorHandling.AllowNonPublicDefaultConstructor进行消息反序列化?

时间:2013-11-13 08:45:45

标签: masstransit

我正在尝试将MassTransit合并到一个也使用NHibernate的项目中。 NHibernate要求我至少拥有一个带有受保护内部可见性的默认构造函数。

我遇到了以下问题。可以毫无问题地发布消息,但处理程序接收具有未初始化成员的消息对象。在对MassTransit源进行一段时间的调试和检查之后,我发现这是由于MassTransit在反序列化期间使用设置ConstructorHandling.AllowNonPublicDefaultConstructor这一事实导致我的受保护内部默认构造函数被调用而不是参数化构造函数。我设法重现了这种行为,请参阅下面的代码。

MassTransit使用AllowNonPublicDefaultConstructor背后的原因是什么,有没有办法改变这种行为?

class Program
{
    public class TestClass
    {
        private readonly string _someString;

        public string SomeString {
            get { return _someString; }
        }

        public TestClass(string someString)
        {
            _someString = someString;
        }

        protected internal TestClass()
        {
            _someString = "uninitialized";
        }
    }

    static void Main(string[] args)
    {
        var obj = new TestClass("Hello World");

        var serializerSettings = new JsonSerializerSettings
                {
                    ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
                    ContractResolver = new ... // MassTransit contract resolver that includes private setters
                };


        string serializedObject = JsonConvert.SerializeObject(obj, serializerSettings);

        var deserializedObj = JsonConvert.DeserializeObject<TestClass>(serializedObject, serializerSettings);

        // deserializedObj.SomeString == "uninitialized"
    }
}

1 个答案:

答案 0 :(得分:1)

消息根本不应该包含任何逻辑。消息是合同。他们中的任何逻辑只会一次又一次地让你感到厌烦。 :(我们将始终使用默认值,无参数,构造函数。如果没有,我们不会反序列化您的消息。

我们建议您总是使用接口而不是具体类型来帮助强制从消息类型中删除逻辑。但是,如果您确实希望有这种行为,那么您需要编写自己的序列化程序。

如果您想进一步讨论,建议您加入邮件列表:groups.google.com/group/masstransit-discuss。