svcutil.exe是xsd.exe的替代品吗?

我正在使用xsd.exe从.xsd文件生成一些c#类。 我遇到了此处和其他网站上涉及的相同问题,其中xsd.exe生成Type []数组,而不是.xsd文件中类型的通用List集合。 有些人建议如果将/ dataContractOnly参数传递给svcutil.exe,svcutil.exe可以用作xsd.exe的替代品。 但是,似乎这些人都错了,因为svcutil.exe实际上生成了System.Xml.XmlNode []数组属性,而不是基于.xsd文件中的模式创建类型。

例如,给定这个简单的.xsd架构:

                

‘xsd.exe / classes Example.xsd’生成:

 public partial class Employees { private Employee[] employeeField; public Employee[] Employee { get { return this.employeeField; } set { this.employeeField = value; } } } public partial class Employee { private string firstNameField; private string lastNameField; public string FirstName { get { return this.firstNameField; } set { this.firstNameField = value; } } public string LastName { get { return this.lastNameField; } set { this.lastNameField = value; } } } 

‘svcutil.exe / target:code / dataContractOnly / serializer:XmlSerializer / importXmlTypes /collectionType:System.Collections.Generic.List`1 Example.xsd’生成:

 public partial class Employee : object, System.Runtime.Serialization.IExtensibleDataObject{ private System.Runtime.Serialization.ExtensionDataObject extensionDataField; private string FirstNameField; private string LastNameField; public System.Runtime.Serialization.ExtensionDataObject ExtensionData{ get{ return this.extensionDataField; } set{ this.extensionDataField = value; } } public string FirstName{ get{ return this.FirstNameField; } set{ this.FirstNameField = value; } } public string LastName{ get{ return this.LastNameField; } set{ this.LastNameField = value; } } } public partial class Employees : object, System.Xml.Serialization.IXmlSerializable{ private System.Xml.XmlNode[] nodesField; private static System.Xml.XmlQualifiedName typeName = new System.Xml.XmlQualifiedName("Employees", "http://tempuri.org/XMLSchema.xsd"); public System.Xml.XmlNode[] Nodes{ get{ return this.nodesField; } set{ this.nodesField = value; } } public void ReadXml(System.Xml.XmlReader reader){ this.nodesField = System.Runtime.Serialization.XmlSerializableServices.ReadNodes(reader); } public void WriteXml(System.Xml.XmlWriter writer){ System.Runtime.Serialization.XmlSerializableServices.WriteNodes(writer, this.Nodes); } public System.Xml.Schema.XmlSchema GetSchema(){ return null; } public static System.Xml.XmlQualifiedName ExportSchema(System.Xml.Schema.XmlSchemaSet schemas){ System.Runtime.Serialization.XmlSerializableServices.AddDefaultSchema(schemas, typeName); return typeName; } } 
  1. svcutil.exe真的应该是xsd.exe的替代品吗? 产生的输出似乎完全不同。

  2. 此时,看起来我将不得不使用xsd.exe从我的.xsd文件创建类,然后手动调整代码以我想要的forms获取它。 我意识到使用纯粹生成的代码是理想的,但我想知道是否有其他人使用xsd.exe作为起点然后在那里工作或者我是否需要考虑另一种方法?

  3. Visual Studio 2010中是否有对xsd.exe的更新?

是的, svcutil.exe 可以用作xsd.exe的替代品,但听起来你无法生成通用集合。 svcutil.exe有一个collectionType开关,允许您指定要用于集合的类型:

 svcutil /o:Svc.cs /ct:System.Collections.Generic.List`1 http://example.com 

澄清

Andrew Hare上面的回答是可行的,但是jameswelle粘贴在他最后一段代码上方的示例命令:

svcutil.exe /target:code /dataContractOnly /serializer:XmlSerializer /importXmlTypes /collectionType:System.Collections.Generic.List`1 Example.xsd

不起作用,因为, 如MSDN所述 ,’。 。 用于引用类型的/ r/ ct开关用于生成数据协定。 使用XmlSerializer时,这些开关不起作用。

HTH。

我只想创建自己的xsd.exe。 很抱歉无法粘贴,但如果您将此代码复制到主页:

  XmlSchemas xsds = new XmlSchemas(); xsds.Add(xsd); xsds.Compile(null, true); XmlSchemaImporter schemaImporter = new XmlSchemaImporter(xsds); // create the codedom CodeNamespace codeNamespace = new CodeNamespace(strNamespace); XmlCodeExporter codeExporter = new XmlCodeExporter(codeNamespace); List maps = new List(); foreach (XmlSchemaType schemaType in xsd.SchemaTypes.Values) { maps.Add(schemaImporter.ImportSchemaType(schemaType.QualifiedName)); } foreach (XmlSchemaElement schemaElement in xsd.Elements.Values) { maps.Add(schemaImporter.ImportTypeMapping(schemaElement.QualifiedName)); } foreach (XmlTypeMapping map in maps) { codeExporter.ExportTypeMapping(map); } ReplaceArrayWithList(codeNamespace); // Check for invalid characters in identifiers CodeGenerator.ValidateIdentifiers(codeNamespace); // output the C# code CSharpCodeProvider codeProvider = new CSharpCodeProvider(); using (StreamWriter writer = new StreamWriter(strCsPath, false)) { codeProvider.GenerateCodeFromNamespace(codeNamespace, writer, new CodeGeneratorOptions()); } } private static void ReplaceArrayWithList(CodeNamespace codeNamespace) { codeNamespace.Imports.Add(new CodeNamespaceImport("System.Collections.Generic")); foreach (CodeTypeDeclaration codeType in codeNamespace.Types) { foreach (CodeTypeMember member in codeType.Members) { if (member is CodeMemberField) { CodeMemberField field = (CodeMemberField)member; if (field.Type.ArrayRank > 0) { CodeTypeReference type = new CodeTypeReference(); type.BaseType = "List<" + field.Type.BaseType + ">"; field.Type = type; } } if (member is CodeMemberProperty) { CodeMemberProperty property = (CodeMemberProperty)member; if (property.Type.ArrayRank > 0) { CodeTypeReference type = new CodeTypeReference(); type.BaseType = "List<" + property.Type.BaseType + ">"; property.Type = type; } } } } } } 

}

我在另一个模式上测试了相同的命令,ang收到了来自svcutil的类似“垃圾”结果。 因此,可能是一种让它像xsd.exe一样工作的方法,但到目前为止,我所看到的远没有那么有用。


更新的答案:我发现当所有引用的XSD被强制包含时,许多这些xml节点的通用数组被强类型替换。 在我的情况下,我有许多xsd文件都相互引用,但svcutil似乎并没有包含它们。 我不得不告诉它使用* .xsd来获取它们。

我发现Xsd2Code比xsd.exe确实要好得多。 请看这里: http : //xsd2code.codeplex.com/