xsd.exe使用数组中的多个元素生成c#
我有一组XML模式文件提供给我。 我无法更改XML,因为这些有时会更新。 我正在使用xsd.exe将架构文件转换为生成的c#代码。 我不能使用任何第三方工具。 其中一个XML模式文件的一部分显示如下:
当转换为c#时,我得到如下结果:
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://abcxyz.com")] public partial class LocationType { private object[] itemsField; private ItemsChoiceType[] itemsElementNameField; /// [System.Xml.Serialization.XmlElementAttribute("Address", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] [System.Xml.Serialization.XmlElementAttribute("City", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] [System.Xml.Serialization.XmlElementAttribute("LocNum", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] [System.Xml.Serialization.XmlElementAttribute("Longitude", typeof(decimal), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] [System.Xml.Serialization.XmlElementAttribute("State", typeof(LocationTypeState), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")] public object[] Items { get { return this.itemsField; } set { this.itemsField = value; } } /// [System.Xml.Serialization.XmlElementAttribute("ItemsElementName")] [System.Xml.Serialization.XmlIgnoreAttribute()] public ItemsChoiceType[] ItemsElementName { get { return this.itemsElementNameField; } set { this.itemsElementNameField = value; } } }
由于这些都生成了部分类,我可以自由添加其他代码。 我需要能够读取/设置各个属性,例如姓名,地址,城市等。
我需要能够序列化这些对象以匹配架构。
在c#中有没有办法创建一个公共属性,以适当的顺序读取或设置Items数组中的值,等等? 即:
public partial class LocationType { public string Address { get { // code here to return the correct Items[] element } set { // code here to set the correct Items[] element } } }
该模式所说的是,如果某个外部类型包含一个类型为LocationType
的元素,那么人们可能希望在其中找到
1)子元素
,OR
2)这些子元素依次为:
,
,
和
。
因此,这里的数据是多态的,即使它没有在xsd.exe生成的c#类中明确建模。 这种情况很有意义 – 可以明确指定位置,也可以间接指定为表中的查找。
当像这样反序列化多态序列时, XmlSerializer
将它找到的每个元素放在对应于序列中元素的数组字段中,在本例中是数组Items
。 此外,应该有另一个由XmlChoiceIdentifierAttribute
属性标识的相应数组字段,在本例中为ItemsElementName
。 此数组中的条目必须与Items
数组1-1对应。 它通过ItemsChoiceType
枚举记录Items
数组的每个索引中反序列化的元素的名称,其枚举名称必须与装饰Items
数组的XmlElementAttribute
属性中的名称匹配。 这允许已知多态数据的特定选择。
因此,为了完善LocationType
类的实现,您需要确定给定的LocationType
是直接还是间接; 获取各种属性; 对于每种类型(直接或间接),设置所有必需的数据。
这是原型。 (你没有在你的问题中包含LocationTypeState
的定义,所以我只是将它视为一个字符串):
public partial class LocationType { public LocationType() { } public LocationType(string locNum) { SetIndirectLocation(locNum); } public LocationType(string name, string address, string city, string state) { SetDirectLocation(name, address, city, state); } public bool IsIndirectLocation { get { return Array.IndexOf(ItemsElementName, ItemsChoiceType.LocNum) >= 0; } } public string Address { get { return (string)XmlPolymorphicArrayHelper.GetItem(Items, ItemsElementName, ItemsChoiceType.Address); } } public string LocNum { get { return (string)XmlPolymorphicArrayHelper.GetItem(Items, ItemsElementName, ItemsChoiceType.LocNum); } } // Other properties as desired. public void SetIndirectLocation(string locNum) { if (string.IsNullOrEmpty(locNum)) throw new ArgumentException(); object[] newItems = new object[] { locNum }; ItemsChoiceType [] newItemsElementName = new ItemsChoiceType [] { ItemsChoiceType.LocNum }; this.Items = newItems; this.ItemsElementName = newItemsElementName; } public void SetDirectLocation(string name, string address, string city, string state) { // In the schema, "City" is mandatory, others are optional. if (string.IsNullOrEmpty(city)) throw new ArgumentException(); List
这是我们从原始答案中学到的最终解决方案。 此静态类用于获取和设置适当的属性。
public static class XmlPolymorphicArrayHelper { public static TResult GetItem(TResult[] items, TIDentifier[] itemIdentifiers, TIDentifier itemIdentifier) { if (itemIdentifiers == null) { return default(TResult); } var i = Array.IndexOf(itemIdentifiers, itemIdentifier); return i < 0 ? default(TResult) : items[i]; } public static void SetItem(ref TResult[] items, ref TIDentifier[] itemIdentifiers, TIDentifier itemIdentifier, TResult value) { if (itemIdentifiers == null) { itemIdentifiers = new[] { itemIdentifier }; items = new[] { value }; return; } var i = Array.IndexOf(itemIdentifiers, itemIdentifier); if (i < 0) { var newItemIdentifiers = itemIdentifiers.ToList(); newItemIdentifiers.Add(itemIdentifier); itemIdentifiers = newItemIdentifiers.ToArray(); var newItems = items.ToList(); newItems.Add(value); items = newItems.ToArray(); } else { items[i] = value; } } }
然后从部分类中调用它们,如下所示:
public partial class LocationType { [XmlIgnore] public string Address { get { return (string)XmlPolymorphicArrayHelper.GetItem(Items, ItemsElementName, ItemsChoiceType.Address); } set { XmlPolymorphicArrayHelper.SetItem(ref this.itemsField, ref this.itemsElementNameField, ItemsChoiceType.Address, value); } } }
这在Items数组上设置/创建了适当的成员,我可以将它用于实现此模式的多个类。
- InvalidOperationException:无法为“Role”创建DbSet,因为此类型未包含在上下文的模型中
- EF:在DbContext上禁用“AutoDetectChangesEnabled”和“ProxyCreationEnabled”时,从多对多关系创建/删除关系
- 扩展ASP.NET标识角色:IdentityRole不是当前上下文模型的一部分
- 如何将查询字符串参数转换为asp.net mvc 4中的路由
- EqualityComparer 。默认与T.Equals
- aync与异步方法中的Task.Result
- 故事板完成后如何调用方法?
- WCF – 使用相同数据协定的多个服务合同
- ODP.Net托管驱动程序 – ORA-12704:生成的代码中的字符集不匹配