[英]Is svcutil.exe a replacement for 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架構:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://tempuri.org/XMLSchema.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/XMLSchema.xsd"
xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:complexType name="Employee">
<xs:all>
<xs:element name="FirstName" type="xs:string"></xs:element>
<xs:element name="LastName" type="xs:string"></xs:element>
</xs:all>
</xs:complexType>
<xs:element name="Employees">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element name="Employee" type="Employee"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
'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;
}
}
svcutil.exe真的應該是xsd.exe的替代品嗎? 產生的輸出似乎完全不同。
此時,看起來我將不得不使用xsd.exe從我的.xsd文件創建類,然后手動調整代碼以獲得我想要的形式。 我意識到使用純粹生成的代碼是理想的,但我想知道是否有其他人使用xsd.exe作為起點然后在那里工作或者我是否需要考慮另一種方法?
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
澄清
安德魯·黑爾的回答上面的工作,但該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<XmlTypeMapping> maps = new List<XmlTypeMapping>();
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;
}
}
}
}
}
}
}
我發現Xsd2Code比xsd.exe確實要好得多。 請看這里: http : //xsd2code.codeplex.com/
我在另一個模式上測試了相同的命令,ang收到了來自svcutil的類似“垃圾”結果。 因此,可能是一種讓它像xsd.exe一樣工作的方法,但到目前為止,我所看到的遠沒有那么有用。
更新的答案:我發現當強制包含所有引用的XSD時,許多這些xml節點的通用數組被強類型替換。 在我的情況下,我有許多xsd文件都相互引用,但svcutil似乎並沒有包含它們。 我不得不告訴它使用* .xsd來獲取它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.