2010-05-12 53 views
6

我有一类汽车和派生跑车:汽车
事情是这样的:C#我怎样才能回到我的基类的web服务

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


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

我有回到汽车方法的web服务,即:

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

它返回:

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

我有另一种方法,一LSO返回汽车这样的:

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

它编译罚款和一切,但调用它,当我得到:
System.InvalidOperationException:有一个错误生成XML文档。 ---> System.InvalidOperationException:类型wsBaseDerived.SportsCar不是预期的。使用XmlInclude或SoapInclude属性指定静态未知的类型。

我发现奇怪的是,它不能将这个序列化为一辆直线汽车,因为mycar是一辆汽车。

上ourse的的WebMethod添加XmlInclude删除错误:

[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> 

但我真正想要的基类返回, 没有额外的属性等来自派生类。

这是否可以不创建mappers等?

请说是;)

+0

你是什么意思创建映射器?你在谈论注释数据合同吗? – Nix 2010-05-12 11:54:10

+0

嗨! 抱歉不清楚,我的意思是没有为汽车/跑车创建手动转换方法。 即 私有静态汽车地图(跑车SC) { 返回新车(){TopSpeed中文= sc.TopSpeed}} 或 丑陋的东西类似的:) – HenriM 2010-05-12 12:13:31

回答

0

无论你想忽略的属性使用XmlIgnoreAttribute。或者更痛苦的方法是为您的属性实施custom serialization

祝你好运。

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

谢谢,但麻烦的是,在现实世界中我有实际上返回“SuperCar”的其他方法,然后需要额外的属性。 – HenriM 2010-05-12 12:33:40

+0

Web服务在“文档交换”类型方法中效果最佳。然后你为这个文档和地图分类。其他任何东西都有问题。 – TomTom 2010-05-14 11:12:36

0

只是一个刺,但你有没有试过这个?投在回报上。

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

试过了,结果相同:( Thx虽然! – HenriM 2010-05-12 12:29:35

+0

我实际上猜测C#编译器会警告一个无用的投射指令 – Dykam 2010-05-12 12:45:27

1

这样做:

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

的原因是XMLSerializer的检查对GetType()类型的对象,并希望它是一样的声明之一。

我知道这是一种痛苦,但我不知道另一种选择。

+0

谢谢,是的,这将起作用 但它基本上与使用Mapper方法相同我称之为它,虽然我会在这个和Car对象下生存下来,但是对于一个真实世界的对象来说它是非常乏味和丑陋的。 我正在寻找一个更一般的可重用解决方案 – HenriM 2010-05-12 12:50:28

+0

根据您的性能限制,可以使用反射来写一个通用的映射器 – 2010-05-14 14:33:22

0

尝试WCF,有[KnownType]。

不过,不知道,但是,如果这可能与oldskool SOAP Web服务,尽管如此。

+0

我必须研究一下,但是从我的搜索结果来看,似乎很像XmlInclude和SoapInclude。可能是错误的,尽管如此。 – HenriM 2010-05-12 13:25:24

+0

当然,它是,对不起。与优雅的演员阵容或者尝试者都不相上下ng XmlRoot - 解决方案(这对我来说更好)。 说实话,我并没有真正体验过旧的webservice风格。使用它们一段时间,但自从微软推出了神奇的,天堂般的,神圣的WCF ...... ;-) – stormianrootsolver 2010-05-12 13:31:25

+0

呵呵我需要看看我理解的WCF。 没有得到XmlRoot的工作,所以现在我需要一些像克隆等转换。 感谢您的答复。 – HenriM 2010-05-12 13:56:50

0

的其他意见和答案在这里让我思考,如果我需要做一个映射法这样吧:

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

} 

和的WebMethod:

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

可正常工作:

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

这打破了在我看来有派生对象的目的,但直到有人想出来另一种解决方案,就是我将飞行的方式...

0

如果你想它总是序列化为“汽车”而不是“SportsCar”添加一个[XmlRoot("Car")]它。

public class Car { 
    //stuff 
} 

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

编辑:使用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

谢谢,但见尼克斯的回答评论,我确实需要Sportstuff。 – HenriM 2010-05-12 13:29:40

+0

嗯。尝试这样做是这样的: [XmlRoot(“汽车”) 公共类跑车:汽车{... 得到了相同的例外,我最初有,InvalidOperationSomething ... 可能是做错了,但。 – HenriM 2010-05-12 13:54:24

+0

您是否使用SportsCar类型或车型创建了序列化程序?无论如何,如果你有时需要跑车(不仅仅是它的元素),这将无法工作,除非你想创建你的序列化程序(巨大的皮塔)时混乱XmlAttributeOverrides 这当然假设你使用XmlSerializer,如果你的usinc wcf忽略所有事情我说:P – 2010-05-12 14:03:27

2

我将实现在基类的拷贝构造函数。

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

然后,您可以基于GetMyCar方法中的SportsCar返回一辆新车。我认为这种方式清楚地表达了该方法的意图。

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

同意,我最喜欢这个“非” - 解决方案:) +1 – HenriM 2010-05-14 11:13:25