2013-11-13 2 views
1

Я пытаюсь включить MassTransit в проект, который также использует NHibernate. NHibernate требует, чтобы у меня был по умолчанию конструктор с защищенной внутренней видимостью.Почему MassTransit использует конструкторHandling.AllowNonPublicDefaultConstructor для десериализации сообщений?

У меня возникла следующая проблема. Сообщения могут быть опубликованы без каких-либо проблем, однако обработчики получают объекты сообщений с неинициализированными членами. После некоторого периода отладки и проверки источников 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

Сообщения не должны иметь никакой логики в них вообще. Сообщения - это контракты. Любая логика в них только закончится тем, что вас снова и снова ударят. :(Мы всегда будем использовать параметр по умолчанию, никакой параметр, конструктор. Если его нет, мы не будем десериализовать ваше сообщение.

Мы предлагаем вам использовать интерфейсы вместо конкретных типов, чтобы помочь устранить логику от типов сообщений.Но если вы действительно хотите иметь это поведение, вам нужно будет написать собственный сериализатор.

Если вы хотите обсудить далее, я предлагаю вам присоединиться к списку рассылки: groups.google.com/ group/masstransit-discuss.

+0

Причина, по которой я использую это частное поле для чтения только для открытого публичного свойства, заключается в том, что это мой предпочтительный (пуристический) способ определения неизменяемого объекта. – fstuijt

+1

Несомненно. Перевести сообщение на объект домена, который имеет любую логику. Сообщения должны быть просто мешками с недвижимостью, больше ничего. У вас есть аргументация, и нет никакого способа изменить это с помощью сериализаторов по умолчанию. – Travis

Смежные вопросы