【问题标题】:WCF Service with abstract class as method parameter以抽象类作为方法参数的 WCF 服务
【发布时间】:2014-09-18 10:44:47
【问题描述】:

示例如下:

[ServiceKnownType("GetKnownTypes", typeof(Helper))]
[ServiceContract]
public interface ICommunicationService
{
    [WebInvoke(Method = "POST",
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare,
        UriTemplate = "/SendMessage")]
    string SendMessage(BusMessage message);
}

    [DataContract]
    [Serializable]
    public abstract class BusMessage
    {
       [DataMember(Name = "uid")]
       public string Id { get; set; }
    }

GetKnownTypes 返回 BusMessage 的所有子类型。

如果我从 wsdl 生成客户端,一切正常。类已正确转换和序列化。

当我尝试使用外部的东西(例如来自 Chrome 的 Postman)时会出现问题。

我收到无法实例化抽象类的异常。

我注意到在从我的客户端进行序列化时,字段“__type”被添加到 json 字符串中。

它包含这样的消息类型:BusTextMessage#namespace。

我尝试将其手动添加为另一个字段,但没有帮助。如何解决这样的问题?

我不应该使用抽象类/接口作为参数吗?

【问题讨论】:

  • 我不知道你为什么要为你的 DataContracts 提供抽象类。 Abstract 用于高级面向对象设计,独立于面向服务的体系结构。删除“抽象”会有什么问题?我的猜测是 WCF 做了一些黑魔法,并从你的继承类中创建了自己的 BusMessage 非抽象类。
  • 当我删除抽象时,它将创建对象 BusMessage,设置此类的所有属性并忽略其他属性,例如 BusTextMessage,如果发送了 BusTextMessage
  • 听起来你有其他类继承了 BusMessage。你能发布一个样本吗?如果你有一个单一的、非抽象的、非继承的 DataContract 类会发生什么?这是实现 WCF DataContracts 的典型且最简单的方法。如果你让它发挥作用,你可以慢慢增加复杂性,看看有什么问题。
  • 我知道出了什么问题。我刚刚创建了 BusMessageDto,其中包含所有继承类的字段,然后将其转换为我的继承结构。问题是序列化程序没有关于类类型的信息
  • 为什么会有问题?根据定义,序列化数据没有类型系统。您可以在数据本身中包含序列化的数据类型,但字符串不知道它包含哪个类。

标签: c# json wcf


【解决方案1】:

当您向 WCF 服务发送“对象”时,发送的并不是真正的对象,而是数据被序列化和反序列化。当您导入服务引用时,您可以看到这是因为客户端只有一个存根类,没有任何方法和底层逻辑。

客户端/服务尝试创建具体类的实例并从数据中反序列化它们。由于无法创建抽象类的实例,因此无法通过 WCF 将抽象类“传递”给方法调用。

另外:抽象的类实际上没有意义,至少在您提供的示例中没有。正如我上面所说,数据合约类中的逻辑不会传播到客户端,因此最好不要在其中包含任何逻辑(方法、复杂的 getter/setter)。如果你介意的话,没有理由让课程abstract

【讨论】:

  • 是的,我不能发送抽象类。那么从 WSDL 生成的 WCF 客户端如何为 ex 发送消息。 BusTextMessage 和后来的 SendMessage 反序列化了吗?正如我所说,它添加了包含命名空间和类名的特殊字段“__type”。但是当我从 PostMan Chrome 发送时它不起作用
  • 这个问题与抽象类无关。这个问题与继承有关。
  • 好吧,如果您删除 abstract 关键字会怎样?那它行得通吗?你得到的实例是什么类型的?是以前的抽象基类还是派生类?我想说,虽然继承可能是问题的一部分,但真正的问题是使用抽象类作为基础。
  • 当我删除摘要时,它会收到 BusMessage 类型的消息,在这种情况下是错误的
  • 那么您没有将正确的数据传递给 WCF 服务。顺便说一句,WCF 不需要同时标记[DataContract][Serializable] 的类。 [DataContract] 就足够了。
猜你喜欢
  • 1970-01-01
  • 2011-06-04
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 2016-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多