我正在尝试从XSD生成代码,该代码具有两个扩展常见complexType的complexType。继承者有一个名为“value”的公共属性,它具有不同的类型。当然,由于XSD规则,我不能把它放在我的基本类型上。我的目的是以多态方式调用基类型上的属性,该类型将调用子类上的正确方法。这可能吗?
这是我的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对象上实现一个“value”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()是一个方法,通过它实际使用的Property的子类来确定应该具有哪种返回类型?请原谅我非常懒惰。我相信it's a virtue。 =)
答案 0 :(得分:2)
您正在反序列化为Property
个对象,因此序列化程序会创建Property
类型的对象。您不会在运行时知道您是否有BoolProperty
或StringProperty
。
您需要从XML中提取StringProperties,将它们反序列化为StringProperty
个对象,然后将其反序列化为BoolProperties。
然后,您可以将它们合并到一个Property
类型的列表中。只要您在基类上创建virtual property
并在实现类中覆盖,该应用就会表现得像预期的那样。
对作者编辑的回复
它不起作用,因为此时没有正确的信息。您必须明确地将对象反序列化为StringProperty
,以使.NET识别您的属性。您永远无法在函数中检测属性类型。
如果你有Property
个正确类型的对象,你可以创建一个扩展方法来促进:
public string GetValue(this Property property)
{
if(property is StringProperty) return ((StringProperty)property).Value;
else if ...
}
但是,您需要知道正确的类型,如果您将实体反序列化为Property
个对象,则不知道该类型。
答案 1 :(得分:1)
我认为不可能按照你想要的方式去做。
但是你可以利用部分类机制。
例如,您可以为Property partial class添加另一个文件,并添加一个名为“public virtual string ValueToString()”的虚拟方法,在StringProperty和BoolProperty中覆盖它(也可以通过部分类机制)。通过这种方式,您可以使foreach工作(调用property.ValueToString())。
当然这意味着你必须在生成类之后进行自定义工作,但我没有看到其他方法。