Порядок сериализации и проблемы с Unity - PullRequest
2 голосов
/ 07 января 2009

У меня есть приложение, использующее XML и пользовательский сериализатор, и недавно я добавил несколько DI, использующих Unity 1.2 для установки двух свойств в моем классе.

Теперь, когда я сериализую класс, свойства, которые были установлены Unity, сначала сериализуются, а затем все остальные свойства по порядку.

Таким образом, если свойства класса 2 и 3 установлены Unity, сериализованный класс получается в следующем порядке: 23145

Для XmlSerialiser я могу использовать атрибут XmlElement, чтобы установить порядок, но мой настраиваемый сериализатор по-прежнему выводит класс в неправильном порядке и в формате фиксированной длины, поэтому порядок важен.

Кто-нибудь знает способ заставить мой класс сериализоваться по порядку, все еще используя Unity?

Спасибо

Примеры кода Класс

 [Serializable]
[DataContract]
[XmlInclude(typeof(HeaderDocument))]
public class HeaderDocument
{
    [InjectionConstructor]
    public HeaderDocument()
    {
        DateTimeCreated  = DateTime.Now;
        TransactionId  = Guid.NewGuid().ToString();
        HasPayload = true;
    }

    /// <summary>Gets or sets the service name of the target service.</summary>
    [DataMember, CopyBookElement("REQUESTED-SERVICE", CopyBookDataType.String, Length = 40)]
    public string ServiceName { get; set; } 

    /// <summary>Gets or sets the entry application name of the request.</summary>
    [DataMember, CopyBookElement("CONSUMER-APPLICATION-ID", CopyBookDataType.UnsignedInteger, Length = 3)]
    public int ApplicationId { get; set; } 

    /// <summary>Gets or sets the quality of service required for the request.</summary>
    [DataMember, CopyBookElement("QUALITY-OF-SERVICE", CopyBookDataType.String, Length = 1)]
    public string QualityOfService { get; set; }

    /// <summary>Gets or sets the transaction identifier.</summary>
    [DataMember, CopyBookElement("TRANSACTION-ID", CopyBookDataType.String, Length = 36)]
    public string TransactionId { get; set; }

    /// <summary>Gets or sets the time the document was created.</summary>
    public DateTime DateTimeCreated { get; set; }

    [DataMember, CopyBookElement("HAS-PAYLOAD", CopyBookDataType.Boolean)]
    public bool HasPayload { get; set; }
}

Конфигурация Unity

<unity>
<typeAliases />
<containers>
  <container name="TechnicalArchitecture">
    <types>
      <type type="ILogger, ApplicationServices" mapTo="Logger, ApplicationServices" />
      <type type="HeaderDocument, ApplicationServices">
        <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
          <property name="ApplicationId" propertyType="System.Int32">
            <value value="19" />
          </property>
          <property name="QualityOfService" propertyType="System.String">
            <value value="1" />
          </property>
        </typeConfig>
      </type>
    </types>
  </container>
</containers>

При создании HeaderDocument я вызываю

HeaderDocument = IOC.Container.Resolve<HeaderDocument>();

Я бы предпочел не изменять пользовательский serilaiser, сейчас я только что добавил свойство 1 в конфигурацию Unity, чтобы я мог провести некоторое тестирование.

Но я действительно хочу знать, почему свойство, заполняемое Unity, обрабатывается иначе, чем свойство, установленное любым другим методом. (Отражение, конструктор или установщик свойств).

1 Ответ

1 голос
/ 07 января 2009

Ну, как ваш заказной сериализатор выбирает порядок? И вы контролируете этот сериализатор? Или это третья сторона? Шаблон «2, 3, 1, 4, 5», который вы описываете, заставляет задуматься, не является ли ваш объект «сумкой свойств», и он просто сериализует данные в порядке их установки - это будет очень рискованно. Порядок, в котором вы устанавливаете свойства, не должен (обычно) иметь значение.

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

Так что вам нужно как-то определить порядок самостоятельно, возможно, в алфавитном порядке (но это хрупко, когда кто-то добавляет свойство AardvarkCount), возможно, через пользовательский атрибут.

У меня есть настраиваемый (двоичный) сериализатор , и я использую подход настраиваемых атрибутов, хотя я поддерживаю алфавитный для некоторых сценариев. Например:

[ProtoContract]
public class MyClass {
    [ProtoMember(1)]
    public int Foo {get;set;}

    [ProtoMember(2)]
    public string Bar {get;set;}
}

Тогда не имеет значения, в каком порядке отражение упорядочивает свойства - сериализатор всегда считывает / записывает данные в порядке Foo, Bar.

(И для наблюдателя: да, приведенный выше пример очень похож на WCF / контракты данных с набором свойств Order, поэтому я тоже это поддерживаю ;-p)

...