2009-12-17 60 views
1

我想從具有兩個擴展公共complexType的complexType的XSD生成代碼。繼承者有一個名爲「value」的公共屬性,它有不同的類型。由於XSD規則,我無法將其放在我的基本類型上。我的目的是多態地調用基類型的屬性,這將調用子類的正確方法。這可能嗎?在代碼生成(通過xsd.exe)類中調用子類屬性

這裏是我的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> 

這將生成以下代碼:

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

這裏就是我想要做的:

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

我試圖實現一個 「值」 Property對象上的getter屬性希望子類的「value」屬性定義可以隱藏它,但事實並非如此這樣的伎倆:

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

後續問題編輯:這些問題的答案證實了我的擔心,這是不可能的。它仍然會是可能的,雖然做以某種方式如下:

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

其中的GetValue()是計算出的方法是什麼返回類型應該憑藉它實際上是使用屬性的子類的有哪些?請原諒我非常懶惰。我被給予相信it's a virtue。 =)

回答

2

您正在反序列化爲Property對象,因此序列化器會創建類型爲Property的對象。您在運行時不會知道您是否有BoolPropertyStringProperty

您需要從XML中提取StringProperties,將它們反序列化爲StringProperty對象,然後對於BoolProperties也是如此。

然後,您可以將它們組合成一個類型爲Property的列表。只要您在您的基類上創建了一個virtual property,並在您的實現類中覆蓋該應用,該應用就會像預期的那樣運行。


迴應筆者的編輯
這是行不通的,因爲你沒有在這一點上正確的信息做。您必須將您的對象明確反序列化爲StringProperty才能讓.NET識別您的資產。你將永遠無法在你的函數中檢測到propertytype。

如果你有正確類型的Property對象,你可以創建一個擴展方法,以方便:

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

然而,你需要知道這裏的正確的類型,你不知道你是反序列化的實體爲Property對象。

+0

我猜測一樣多。如果沒有擴展和覆蓋的XSD限制,我認爲這會更容易。謝謝你! – Jeremy 2009-12-17 15:55:03

1

我不認爲有可能以你想要的方式去做。

雖然你可以利用分類機制。

例如,您可以爲Property partial類添加另一個文件,並添加一個名爲「public virtual string ValueToString()」的虛擬方法,在StringProperty和BoolProperty中重寫它(也可以通過部分類機制) 。這樣你就可以做foreach工作(調用property.ValueToString())。

當然這意味着您必須在生成類之後進行自定義工作,但我沒有看到其他方法。

+0

感謝您的照明快速回復!不過,我有一個後續問題。 – Jeremy 2009-12-17 15:36:51