2009-12-17 58 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