2011-10-06 140 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'。甚至在那裏,只有默認值。 –