2011-10-06 21 views
5

Tengo un archivo xsd del cual estoy generando una clase C#. Para facilitar el mantenimiento, me gustaría definir una enumeración dentro del archivo xsd solo para que cuando tenga que cambiar la enumeración, solo tenga que actualizarla en un solo lugar. Sé cómo crear la enumeración, pero cuando se genera el código C#, necesito los miembros de enumeración tener valores personalizados, por lo que el resultado sería similar a:Convertir ens xsd a C#

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

¿Hay alguna manera de escribir el xsd a lograr esto?

+0

¿Está escribiendo su propia herramienta para generar el código C#, o hay alguna herramienta estándar que generó el código C# de XSD? – BlueMonkMN

+0

Ahora estoy usando xsd.exe. Realmente no tengo tiempo para crear mi propia herramienta. –

Respuesta

6

Puede agregar anotaciones específicas para la generación de código (esto solo funciona para svcutil, no para xsd.exe) en su archivo xsd.La definición XSD para su enumeración sería algo como esto:

<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> 

Estas anotaciones permiten definir explícitamente el valor numérico de cada valor de enumeración. Puede encontrar un ejemplo on this msdn page si busca "EnumerationValue".

Actualización: John Saunders afirma correctamente en su comentario que esto no funciona si usa xsd.exe. Sin embargo, si usa svcutil.exe para crear el código C#, entonces las anotaciones funcionarán.

Ejemplo de uso de svcutil.exe:

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

Si utiliza svcutil en lugar de xsd.exe, a continuación, el código generado será ligeramente diferente. La diferencia más importante es que svcutil generará atributos para DataContractSerialization en lugar de XmlSerialization.

+0

-1: enlace interesante, y no sabía acerca de esta característica; pero si el OP está usando XSD.EXE, entonces está usando Serialización XML, y 'EnumerationValue' es una característica del Serializador de Contrato de Datos. –

+0

@John: Sí, es cierto que esto es para el serializador de contrato de datos, pensé que también funcionaría para 'xsd.exe'. Sin embargo, si usa 'svcutil' para crear el código del archivo xsd, entonces las anotaciones funcionan. –

+0

La razón por la que estoy usando xsd es porque no sabía que podía hacerlo de otra manera. Si bien esto puede terminar siendo más de codificación de lo que me gustaría poner en él, la respuesta es perfecta para lo que estoy buscando. –

2

Creo enumeraciones XSD son una aplicación más purista de enumeraciones que las enumeraciones de .NET en el sentido de que no es necesario y don No admite valores numéricos asociados con los nombres enumerados. Por supuesto, el código generado, que es un código .NET, asociará un valor numérico con cada valor nombrado internamente, pero este es un detalle de implementación que no es inherente a la naturaleza de una enumeración según lo define el estándar XSD. En esta implementación purista de una enumeración, creo que la forma correcta de asociar valores numéricos explícitos con cada nombre enumerado sería definir una colección/clase separada que vincule valores enumerados con valores numéricos. O define valores enumerados adicionales que representan los valores combinados que admite (NewInstallOrModify).

Editar:

He aquí una muestra de lo que un convertidor podría ser similar.

// 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); 
    } 
} 

Edición 2:

Si su enumeración comienza en 0 (como su ejemplo hace) estos dos cambios son necesarios para mi ejemplo:

Actualizado convertidor int:

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

La línea después de int log debe ser:

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

Gracias. ¿Tiene un enlace que muestre una muestra de una clase que vincule los valores? –

+0

@Drew Burchett: depende de cómo va a usarlo, pero he agregado un código que funciona para su ejemplo y supone que desea que otras enumeraciones se representen de manera similar con potencias de 2. – BlueMonkMN

2

El concepto de "enumeración" en XSD no tiene nada que ver con el concepto de "enumeración" en C#.

"enumeración" en XML Schema es una forma de restringir los posibles valores léxicos de un tipo a enumerado lista de valores. Por ejemplo:

<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> 

Este tipo restringe el espacio de valores para el conjunto de los meses de verano "" (julio, agosto y septiembre).

Claramente, esto no tiene correspondencia con una "enumeración" en C# o cualquier otro lenguaje de programación que conozco.

+0

Mientras entiendo lo que usted ' Dicho esto, xsd.exe convertirá una enumeración xsd en una enumeración C#, por lo que hay cierta correlación. Simplemente no va tan profundo como esperaba. –

+0

Convierte _some_ xsd enumeraciones en 'enum'. E incluso allí, solo con valores predeterminados. –