Вызов свойств подкласса в сгенерированных кодом (через xsd.exe) классах - PullRequest
1 голос
/ 17 декабря 2009

Я пытаюсь сгенерировать код из 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);
            }

Я пытался реализовать свойство get «value» для объекта Property, надеясь, что определения свойства «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? Извините за то, что я чрезвычайно ленив. Мне дано поверить, что это добродетель . =) * +1022 *

Ответы [ 2 ]

2 голосов
/ 17 декабря 2009

Вы десериализуетесь в Property объекты, поэтому сериализатор создает объекты типа Property. Вы не будете знать во время выполнения, был ли у вас BoolProperty или StringProperty.

Вам нужно извлечь StringProperties из XML, десериализовать их в 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 голос
/ 17 декабря 2009

Я не думаю, что возможно сделать это так, как вы пытаетесь.

Хотя вы можете воспользоваться механизмом частичных классов.

Например, вы можете добавить еще одинфайл для частичного класса Property и добавьте виртуальный метод, называемый чем-то вроде «public virtual string ValueToString ()», переопределите его в StringProperty и BoolProperty (также с помощью механизма частичных классов).Таким образом, вы сможете заставить foreach работать (вызывайте property.ValueToString ()).

Конечно, это означает, что вы должны выполнять пользовательскую работу после генерации классов, но я не вижу других способов.

...