views:

293

answers:

1

I have an application that uses an XML and custom serialiser, and have recently added some DI using Unity 1.2 to set two properties in my class.

Now when I serialise the class the properties that were set by Unity are serialised first followed by all the other properties in order.

So if class Properties 2 and 3 are set by Unity the serialised class comes out in the following orger: 23145

For the XmlSerialiser i can use the XmlElement attribute to set the order, but my custom serialiser is still outputting the class in the wrong order, and its in a fixed lenght format so the order is important.

Does any one know of a way to get my class to serialise in order while still using Unity?

Thanks

Code examples Class

 [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 Configuration

<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>

When constructing a HeaderDocument I call

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

I'd prefer not to have to modify the custom serilaiser, currently I've just added property 1 to the Unity configuration for now so i can do some testing.

But what I realy want to know is why a property populated by Unity is treated differently to a property set by any other method. (Reflection, Constructor or Property setter).

+1  A: 

Well, how does your custom serializer choose the order? And do you control this serializer? Or is it 3rd party? The "2, 3, 1, 4, 5" pattern you describe makes we wonder if your object isn't a "property bag", and it is simply serializing data in the order it was set - this would be highly risky. The order in which you set properties shouldn't (normally) matter.

Properties do not have a defined order, and you should not rely on this order between builds. The system also makes no guarantee re the order of properties from reflection vs source code vs anything in fact.

So you need to define the order yourself somehow, perhaps alphabetically (but this is brittle when somebody adds an AardvarkCount property), perhaps via a custom attribute.

I have a custom (binary) serializer, and I use the custom attribute approach, although I support alphabetical for some scenarios. For example:

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

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

Then it doesn't matter in what order reflection orders the properties - the serializer always reads/writes data in the order Foo, Bar.

(And for the observant: yes, the above example looks a lot like WCF / data-contracts with the Order property set, so I support that too ;-p)

Marc Gravell