C#, Как я могу возвратить свой базовый класс в веб-сервисе

У меня есть класс Автомобиль и полученный SportsCar: Автомобиль
Что-то вроде этого:

public class Car
{
    public int TopSpeed{ get; set; }
}


public class SportsCar : Car
{
    public string GirlFriend { get; set; }
}

У меня есть веб-сервис с методами, возвращая Автомобили т.е.:

[WebMethod]
public Car GetCar()
{
    return new Car() { TopSpeed = 100 };
}

Это возвращается:

<Car>
<TopSpeed>100</TopSpeed>
</Car>

У меня есть другой метод, который также возвращает автомобили как это:

[WebMethod]
public Car GetMyCar()
{
    Car mycar = new SportsCar() { GirlFriend = "JLo", TopSpeed = 300 };
    return mycar;
}

Это компилирует прекрасный и все, но при вызове его я добираюсь:
Система. InvalidOperationException: была ошибка при генерации XML-документа.---> Система. InvalidOperationException: тип wsBaseDerived. SportsCar не ожидался. Используйте атрибут XmlInclude или SoapInclude для определения типов, которые не известны статически.

Я нахожу это странным, что это не может сериализировать это как прямой автомобиль, поскольку mycar является автомобилем.

Добавление XmlInclude на WebMethod ourse удаляет ошибку:

[WebMethod]
[XmlInclude(typeof(SportsCar))]
public Car GetMyCar()
{
    Car mycar = new SportsCar() { GirlFriend = "JLo", TopSpeed = 300 };
    return mycar;
}

и это теперь возвращается:

<Car xsi:type="SportsCar">
    <TopSpeed>300</TopSpeed>
    <GirlFriend>JLo</GirlFriend>
</Car>

Но я действительно хочу возвращенный базовый класс без дополнительных свойств и т.д. от производного класса.

Это вообще возможно, не создавая картопостроители и т.д.?

Скажите да ;)

6
задан HenriM 12 May 2010 в 11:49
поделиться

7 ответов

Другие комментарии и ответы заставили меня задуматься, и если мне нужно создать Mapper-метод, пусть будет так:

public class Car: ICloneable
{
    public int TopSpeed{ get; set; }
    public object Clone()
    {
        return new Car() { TopSpeed = this.TopSpeed };
    }

}

и веб-метод:

[WebMethod]
public Car GetMyNewCar()
{
    Car mycar = new SportsCar() { GirlFriend = "HiLo", TopSpeed = 300 };            
    return (Car)mycar.Clone();
}

Это работает, как ожидалось:

<Car>
    <TopSpeed>300</TopSpeed>
</Car>

Это противоречит цели имея производный объект, на мой взгляд, но пока кто-то не предложит другое решение, я буду летать так ...

0
ответ дан 17 December 2019 в 18:11
поделиться

Сделайте следующее:

[WebMethod]
public Car GetMyCar()
{
    Car mycar = new SportsCar() { GirlFriend = "JLo", TopSpeed = 300 };
    return new Car() {TopSpeed = mycar.TopSpeed};
}

Причина в том, что XMLSerializer проверяет тип GetType () объекта и ожидает, что он будет таким же, как объявленный.

Я знаю, что это больно, но не знаю альтернативы.

1
ответ дан 17 December 2019 в 18:11
поделиться

Либо используйте XmlIgnoreAttribute для атрибутов, которые вы хотите игнорировать. Или еще более болезненным способом было бы реализовать настраиваемую сериализацию для ваших атрибутов.

Удачи.

public class SportsCar : Car
{
  [XmlIgnoreAttribute]
  public string GirlFriend { get; set; }
}
0
ответ дан 17 December 2019 в 18:11
поделиться

Просто попытка, но вы пробовали это? Каст на возврат.

[WebMethod]
public Car GetMyCar()
{
    Car mycar = new SportsCar() { GirlFriend = "JLo", TopSpeed = 300 };
    return (Car)mycar;
}
0
ответ дан 17 December 2019 в 18:11
поделиться

Попробуйте WCF, есть [KnownType].

Однако не знаю, возможно ли это с помощью старых веб-сервисов SOAP.

0
ответ дан 17 December 2019 в 18:11
поделиться

Если вы хотите, чтобы он всегда сериализовался как "Car" вместо "SportsCar", добавьте к нему [XmlRoot("Car")].

public class Car {
  //stuff
}

[XmlRoot("Car")]
public class SportsCar {
  //Sporty stuff
}

Edit: Используя XmlSerializer следующим образом:

XmlSerializer ser = new XmlSerializer(typeof(SportsCar));
SportsCar car = new SportsCar()
//stuff
ser.Serialize(Console.out, car)

вы должны получить

<Car>
  <TopSpeed>300</TopSpeed>
  <GirlFriend>JLo</GirlFriend>
</Car>
0
ответ дан 17 December 2019 в 18:11
поделиться

Я бы реализовал конструктор копирования в базовом классе.

    public class Car
    {
        public int TopSpeed { get; set; }

        public Car(Car car)
        {
            TopSpeed = car.TopSpeed;
        }

        public Car()
        {
            TopSpeed = 100;
        }
    }

    public class SportsCar : Car
    {
        public string GirlFriend { get; set; }
    }

Затем вы можете вернуть новый Автомобиль на основе SportsCar в GetMyCar-методе. Я думаю, что это ясно выражает цель метода.

    public Car GetMyCar()
    {
        var sportsCar = new SportsCar { GirlFriend = "JLo", TopSpeed = 300 };
        return new Car(sportsCar);
    }
2
ответ дан 17 December 2019 в 18:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: