简体   繁体   English

C#如何在Web服务中返回我的基类

[英]C# How can I return my base class in a webservice

I have a class Car and a derived SportsCar: Car 我有一辆Car和一辆派生的SportsCar:Car
Something like this: 像这样的东西:

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


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

I have a webservice with methods returning Cars ie: 我有一个Web服务,返回汽车的方法,即:

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

It returns: 它返回:

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

I have another method that also returns cars like this: 我有另一种方法也返回这样的汽车:

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

It compiles fine and everything, but when invoking it I get: 它编译精细和一切,但在调用它时,我得到:
System.InvalidOperationException: There was an error generating the XML document. System.InvalidOperationException:生成XML文档时出错。 ---> System.InvalidOperationException: The type wsBaseDerived.SportsCar was not expected. ---> System.InvalidOperationException:不期望wsBaseDerived.SportsCar类型。 Use the XmlInclude or SoapInclude attribute to specify types that are not known statically. 使用XmlInclude或SoapInclude属性指定静态未知的类型。

I find it strange that it can't serialize this as a straight car, as mycar is a car. 我觉得奇怪的是,因为mycar是一辆汽车所以它不能将其序列化为直车。

Adding XmlInclude on the WebMethod of ourse removes the error: 在WebMethod上添加XmlInclude可以消除错误:

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

and it now returns: 它现在返回:

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

But I really want the base class returned, without the extra properties etc from the derived class. 但我真的希望返回基类,而不需要派生类的额外属性等。

Is that at all possible without creating mappers etc? 如果没有创建映射器等,这是可能的吗?

Please say yes ;) 请说是;)

I would implement a copy constructor in the base class. 我会在基类中实现一个复制构造函数。

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

Then you can return a new Car based on the SportsCar in the GetMyCar-method. 然后你可以在GetMyCar方法中根据SportsCar返回一辆新车。 I think this way clearly express the intent of the method. 我认为这种方式清楚地表达了该方法的意图。

    public Car GetMyCar()
    {
        var sportsCar = new SportsCar { GirlFriend = "JLo", TopSpeed = 300 };
        return new Car(sportsCar);
    }

Do this: 做这个:

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

The reason is that XMLSerializer inspects the GetType() type of the object and expects it to be the same as the declared one. 原因是XMLSerializer检查对象的GetType()类型,并期望它与声明的对象相同。

I know it's a pain but i don't know of an alternative. 我知道这是一种痛苦,但我不知道另一种选择。

Either use XmlIgnoreAttribute on the attributes you want to ignore. 对要忽略的属性使用XmlIgnoreAttribute Or the even more painful way would be to implement a custom serialization for your attributes. 或者更痛苦的方法是为您的属性实现自定义序列化

Good luck. 祝好运。

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

Just a stab, but have you tried this? 只是一个刺,但你试过这个吗? Cast on the return. 投在回归。

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

Try WCF, there is [KnownType]. 尝试WCF,有[KnownType]。

Don't know, however, if thats possible with oldskool SOAP webservices, though. 但是,不知道是否可以使用oldskool SOAP Web服务。

The other comments and answers here got me thinking, and if I need to make a Mapper-method so be it: 这里的其他评论和答案让我思考,如果我需要制作一个Mapper方法,那就这样吧:

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

}

and the webmethod: 和web方法:

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

This works as expected: 这按预期工作:

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

This defeats the purpose of having a derived object in my view, but until someone comes up with another solution thats the way I'll fly... 这违背了我在视图中使用派生对象的目的,但直到有人提出另一种解决方案,就像我将要飞行一样...

If you want it to always serialize as "Car" instead of "SportsCar" add an [XmlRoot("Car")] to it. 如果您希望它始终序列化为“Car”而不是“SportsCar”,则[XmlRoot("Car")]添加[XmlRoot("Car")]

public class Car {
  //stuff
}

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

Edit: Using the XmlSerializer like this: 编辑:像这样使用XmlSerializer:

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

you should get 你应该得到

<Car>
  <TopSpeed>300</TopSpeed>
  <GirlFriend>JLo</GirlFriend>
</Car>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM