2011-10-06 179 views
5

我有一个xsd文件,我从中生成一个C#类。为了提供更简单的维护,我只想在xsd文件中定义一个枚举,这样当我必须更改枚举时,我只需要在一个地方更新枚举。我知道如何创建枚举,但生成的C#代码时,我需要的枚举成员有自定义值,所以结果将类似于:将xsd枚举转换为C#

public enum SetupTypeEnum { 
    None = 0, 
    NewInstall = 1, 
    Modify = 2, 
    Upgrade = 4, 
    Uninstall = 8 
} 

有没有办法写XSD到完成这个?

+0

你正在编写自己的工具来生成C#代码,还是有一些标准的工具从XSD生成C#代码? – BlueMonkMN

+0

现在我正在使用xsd.exe。我真的没有时间去创建自己的工具。 –

回答

6

您可以将特定于代码生成的注释(仅适用于svcutil,不适用于xsd.exe)添加到您的xsd文件。您枚举的XSD定义是这样的:

<xs:simpleType name="SetupTypeEnum"> 
    <xs:restriction base="xs:string"> 
     <xs:enumeration value="None"> 
      <xs:annotation> 
       <xs:appinfo> 
        <EnumerationValue xmlns="http://schemas.microsoft.com/2003/10/Serialization/">0</EnumerationValue> 
       </xs:appinfo> 
      </xs:annotation> 
     </xs:enumeration> 
     <xs:enumeration value="NewInstall"> 
      <xs:annotation> 
       <xs:appinfo> 
        <EnumerationValue xmlns="http://schemas.microsoft.com/2003/10/Serialization/">1</EnumerationValue> 
       </xs:appinfo> 
      </xs:annotation> 
     </xs:enumeration> 
     ... 
    </xs:restriction> 
</xs:simpleType> 

这些注解允许你明确地定义每个枚举值的数值。如果您搜索“EnumerationValue”,则可以找到示例on this msdn page

更新:约翰桑德斯在他的评论中正确地指出,如果您使用xsd.exe,这不起作用。但是,如果使用svcutil.exe创建C#代码,则注释将起作用。

使用svcutil.exe的实施例:

svcutil /dconly "D:\test.xsd" /o:"D:\test.cs" 

如果使用svcutil代替xsd.exe,然后将所生成的代码将被稍有不同。最重要的区别是svcutil将为DataContractSerialization而不是XmlSerialization生成属性。

+0

-1:有趣的链接,我不知道这个功能;但是如果OP使用XSD.EXE,那么他使用的是XML序列化,'EnumerationValue'是Data Contract Serializer的一个特性。 –

+0

@John:是的,这确实是针对数据协定序列化的,我认为它也适用于'xsd.exe'。但是,如果您使用'svcutil'从xsd文件创建代码,则注释将起作用。 –

+0

我使用xsd的原因是因为我没有意识到我可以用其他方式来完成。虽然这可能最终会比我想要的更多的编码,但答案实际上是我所需要的。 –

2

相信XSD枚举是一个更纯粹的执行枚举比在某种意义上说,他们不需要和唐.NET枚举不支持与枚举名称关联的数字值。当然,生成的代码(即.NET代码)将在内部将数值与每个命名值相关联,但这是一个实现细节,并非由XSD标准定义的枚举性质所固有的。在这个纯粹的枚举实现中,我认为将显式数值与每个枚举名称相关联的正确方法是定义一个将枚举值链接到数值的单独集合/类。或者定义表示您支持的组合值(NewInstallOrModify)的其他枚举值。

编辑:

这里是一个什么样的转换器可能看起来像一个样本。

// Generated code 
public enum SetupTypeEnum 
{ 
    None, 
    NewInstall, 
    Modify, 
    Upgrade, 
    Uninstall 
} 
// End generated code 

public struct IntMappedEnum<T> where T : struct 
{ 
    public readonly int originalValue; 

    public IntMappedEnum(T value) 
    { 
    originalValue = (int)Enum.ToObject(typeof(T), value); 
    } 

    public IntMappedEnum(int originalValue) 
    { 
    this.originalValue = originalValue; 
    } 

    public static implicit operator int(IntMappedEnum<T> value) 
    { 
    return 1 << value.originalValue; 
    } 

    public static implicit operator IntMappedEnum<T>(T value) 
    { 
    return new IntMappedEnum<T>(value); 
    } 

    public static implicit operator IntMappedEnum<T>(int value) 
    { 
    int log; 
    for (log = 0; value > 1; value >>= 1) 
     log++; 
    return new IntMappedEnum<T>(log); 
    } 

    public static explicit operator T(IntMappedEnum<T> value) 
    { 
    T result; 
    Enum.TryParse<T>(value.originalValue.ToString(), out result); 
    return result; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
    SetupTypeEnum s = SetupTypeEnum.Uninstall; 
    IntMappedEnum<SetupTypeEnum> c = s; 
    int n = c; 
    IntMappedEnum<SetupTypeEnum> c1 = n; 
    SetupTypeEnum s1 = (SetupTypeEnum)c1; 
    Console.WriteLine("{0} => {1} => {2}", s, n, s1); 
    } 
} 

编辑2:

如果你的枚举从0开始(如你的例子一样)这两个变化是必要的,我的例子:

更新INT转换器:

public static implicit operator int(IntMappedEnum<T> value) 
{ 
    return (value.originalValue == 0)?0:1 << (value.originalValue - 1); 
} 

int log后的行应该是:

for (log = 0; value > 0; value >>= 1) 
+0

谢谢。你有链接会显示一个链接值的类的样本吗? –

+0

@Drew Burchett:这取决于你将如何使用它,但我添加了适用于你的例子的代码,并且假设你希望其他枚举类似地以2的幂来表示。 – BlueMonkMN

2

XSD中“枚举”的概念与C#中的“枚举”概念无关。

XML Schema中的“枚举”是一种将一种类型的可能词汇值限制为枚举值的列表。例如:

<xs:simpleType name="SummerMonth"> 
    <xs:restriction base="xs:gMonth"> 
     <xs:enumeration value="--07"/> 
     <xs:enumeration value="--08"/> 
     <xs:enumeration value="--09"/> 
    </xs:restriction> 
</xs:simpleType> 

此类型将值空间限制为“夏季”月份(7月,8月和9月)的集合。显然,这与C#或我知道的任何其他编程语言中的“枚举”没有对应关系。

+0

虽然我理解你的“再说,xsd.exe会将xsd枚举转换为C#枚举,所以存在一些相关性。它只是没有我希望的那么深。 –

+0

它会将_some_ xsd枚举转换为'enum'。甚至在那里,只有默认值。 –