I know we can enforce generating the members within the classes in the same order as within the members-collection as stated on MSDN. However I look for some code that also adds a serialization-attribute providing the order of those members. So this is what I want the generator to create:
class MyClass
{
[XmlElement("TheProperty", Order = 0]
public int MyProperty { get; set; }
[XmlElement("AnotherProperty", Order = 1]
public int AnotherProperty { get; set; }
}
Currently I have an approach that loops the members of all types within my DOM and appends the attribute to the CustomAttributes
-member of the current (public
) property or field.
var types = code.Types.Cast<CodeTypeDeclaration>().Where(x => !x.IsEnum);
foreach (var members in types.Select(x => x.Members.Cast<CodeTypeMember>()))
{
int i = 0;
var propertiesAndFields = members.Where(x => (
x.Attributes & MemberAttributes.Private) != MemberAttributes.Private
&& (x is CodeMemberField || x is CodeMemberProperty));
foreach (CodeTypeMember member in propertiesAndFields)
{
var attr = member.CustomAttributes.Cast<CodeAttributeDeclaration>().FirstOrDefault(x => x.Name == "System.Xml.Serialization.XmlElementAttribute");
if (attr == null)
{
attr = new CodeAttributeDeclaration("System.Xml.Serialization.XmlElementAttribute");
member.CustomAttributes.Add(attr);
}
attr.Arguments.Add(new CodeAttributeArgument("Order", new CodePrimitiveExpression(i++)));
}
}
However this seems quite hacky to me and I wonder if there were a member built into CodeDOM that creates the Order
-attributes. I remember the Xsd-tool (which I want to extent with custom behaviour using CodeDOM and which uses the same classes and interfaces) is able to append those attributes.
EDIT: The codeDOM is created using the XmlSchemaImporter
- and XmlCodeExporter
-class as mentioned on MSDN:
XmlSchemas schemas = new XmlSchemas();
schemas.Add(schema);
// Create the importer for these schemas.
XmlSchemaImporter importer = new XmlSchemaImporter(schemas);
// System.CodeDom namespace for the XmlCodeExporter to put classes in.
CodeNamespace code = new CodeNamespace(targetNamespace);
XmlCodeExporter exporter = new XmlCodeExporter(code);
// Iterate schema top-level elements and export code for each.
foreach (XmlSchemaElement element in schema.Elements.Values)
{
// Import the mapping first.
XmlTypeMapping mapping = importer.ImportTypeMapping(element.QualifiedName);
// Export the code finally
exporter.ExportTypeMapping(mapping);
}
I can´t see a way to provide the order-attributes here, this is why I want to set them after the DOM has already been created.
There is no build in way in CodeDOM, the right way is to add XmlAttributes, but there is problem with them, because they don't gather along with inheritance. So is better to emit the properties in right order, then the xml serializer will serialize it in the right order(not guaranteed but I have tested it). Hope it works! :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With