2009-12-17 5 views
1

J'essaie de générer du code à partir d'un XSD qui a deux types complexes qui étendent un complexType commun. Les héritiers ont une propriété commune appelée "valeur", qui a différents types. Bien sûr, je ne peux pas le mettre sur mon type de base en raison des règles XSD. Mon intention est d'appeler polymorphiquement la propriété sur le type de base qui invoquerait la bonne méthode sur la sous-classe. Est-ce possible?Appel des propriétés de sous-classes dans les classes générées par le code (via xsd.exe)

Voici mon XSD

<xs:complexType name="Property"> 
    <xs:attribute name="name" type="xs:string" use="required"/> 
</xs:complexType> 
<xs:complexType name="StringProperty"> 
    <xs:complexContent> 
     <xs:extension base="Property"> 
      <xs:attribute name="value" type="xs:string" use="required"/> 
     </xs:extension> 
    </xs:complexContent> 
</xs:complexType> 
<xs:complexType name="BooleanProperty"> 
    <xs:complexContent> 
     <xs:extension base="Property"> 
      <xs:attribute name="value" type="xs:boolean" use="required"/> 
     </xs:extension> 
    </xs:complexContent> 
</xs:complexType> 

Cela génère le code suivant:

public partial class Property { 

    private string nameField; 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string name { 
     get { 
      return this.nameField; 
     } 
     set { 
      this.nameField = value; 
     } 
    } 
} 

public partial class StringProperty : Property { 

    private string valueField; 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string value { 
     get { 
      return this.valueField; 
     } 
     set { 
      this.valueField = value; 
     } 
    } 
} 

public partial class BoolProperty : Property { 

    private bool valueField; 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public bool value { 
     get { 
      return this.valueField; 
     } 
     set { 
      this.valueField = value; 
     } 
    } 
} 

Et voici ce que je veux faire:

  // ConfigProperties is an array of Property objects 
      foreach (Property property in config.ConfigProperties) 
      { 
       // Doesn't compile since Property.value doesn't exist in the base class. 
       Console.WriteLine(property.value); 
      } 

J'ai essayé de mettre en œuvre une "valeur" propriété getter sur l'objet Property en espérant que les définitions de propriété "value" des sous-classes le masqueraient, mais cela ne faire l'affaire:

public partial class Property 
{ 
    public virtual string value 
    { 
     get { throw new NotImplementedException(); } // this method is called instead of the Property subclass methods 
    } 
} 

QUESTION DE SUIVI EDIT: Les réponses confirment mes craintes que cela est impossible. Serait-il encore possible que de faire ce qui suit d'une certaine manière:

  foreach (Property property in config.ConfigProperties) 
      { 
       somevalue = property.GetValue(); 
      } 

où GetValue() est une méthode qui figure sur ce type de retour, il doit avoir en vertu de la sous-classe de la propriété qu'il utilise réellement? Pardonnez-moi d'être extrêmement paresseux. Je suis donné à croire que it's a virtue. =)

Répondre

2

Vous désérialisez en Property objets, par conséquent le sérialiseur crée des objets du type Property. Vous ne saurez pas à l'exécution si vous avez eu un BoolProperty ou un StringProperty.

Vous devez extraire les StringProperties du XML, les désérialiser en StringProperty objets, puis la même chose pour BoolProperties.

Vous pouvez ensuite les combiner en une liste de type Property. L'application se comporte alors comme prévu tant que vous créez un virtual property sur votre base de données que vous remplacez dans vos classes d'implémentation.


réponse à modifier l'auteur
Il ne fonctionnera pas, comme vous n'avez pas les informations correctes à ce moment-là. Vous devrez désérialiser explicitement votre objet en tant que StringProperty pour que .NET reconnaisse votre propriété. Vous ne serez jamais capable de détecter le type de propriété dans votre fonction.

Si vous avez Property objets du type correct, vous pouvez créer une méthode d'extension pour faciliter:

public string GetValue(this Property property) 
{ 
    if(property is StringProperty) return ((StringProperty)property).Value; 
    else if ... 
} 

Cependant, vous devez connaître le type correct ici, que vous ne savez pas si vous désérialisation votre entités comme Property objets.

+0

Je l'ai deviné autant. Je pense que cela aurait été plus facile s'il n'y avait pas les limitations XSD sur les extensions et les remplacements. Merci, Jan! – Jeremy

1

Je ne pense pas qu'il soit possible de le faire comme vous le souhaitez.Cependant, vous pouvez tirer parti du mécanisme des classes partielles. Par exemple, vous pouvez ajouter un autre fichier pour la classe partielle Property et ajouter une méthode virtuelle appelée quelque chose comme "chaîne virtuelle publique ValueToString()", la remplacer dans StringProperty et BoolProperty (également au moyen du mécanisme de classes partielles) . De cette façon, vous pourriez faire fonctionner le foreach (appelez property.ValueToString()).

Bien sûr, cela signifie que vous devez effectuer un travail personnalisé après la génération des classes, mais je ne vois pas d'autres moyens.

+0

Merci pour les réponses rapides à l'éclairage! J'ai une question de suivi ci-dessus cependant. – Jeremy

Questions connexes