【问题标题】:WCF: Use custom class in callbackWCF:在回调中使用自定义类
【发布时间】:2011-06-21 19:15:23
【问题描述】:

我已经设法让 WCF 回调(通过 NamedPipes)与字符串一起使用,但遗憾的是我无法让它与自定义类一起使用。

这是服务声明 + 实现: http://pastebin.com/Zayi2kjT

这是我的数据合同: http://pastebin.com/wFCxrRcJ

这是我在客户端所做的: http://pastebin.com/jxEbyEtP

当我改变时

    public void Send()
    {
        try
        {
            channel.OnCallback("I love deadlines. I like the whooshing sound they make as they fly by.");
        }
        catch (Exception ex)
        {
            Form1.AddText(ex.GetType() + "|" + ex.Message);
        }
    }

channel.OnCallback(new TransmissionClass("I love deadlines. I like the whooshing sound they make as they fly by."));

调用回调方法时,服务器出现以下异常(见上文):

System.ServiceModel.FaultException
Der Formatierer hat beim Deserialisieren der Nachricht eine Ausnahme ausgelöst:   
Fehler beim Deserialisieren von Parameter http://tempuri.org/:aUpdatedObject.  
Die InnerException-Nachricht war "Das Element "http://tempuri.org/:aUpdatedObject"  
enthält Daten eines Typs, der dem Namen "http://schemas.datacontract.org/2004/07
/ServerApp:TransmissionClass" zugeordnet ist.   
Dem Deserialisierungsprogramm ist kein Typ bekannt, der diesem Namen zugeordnet ist.  
Verwenden Sie ggf. einen DataContractResolver, oder fügen Sie den entsprechenden Typ für "TransmissionClass" der Liste der bekannten Typen hinzu.  
Verwenden Sie dazu z. B. das Attribut "KnownTypeAttribute", oder fügen Sie den Typ der an DataContractSerializer übergebenen Liste von bekannten Typen hinzu.".  
Weitere Details finden Sie unter "InnerException".

但是,我已将 KnownTypeAttribute 应用于 WCF 服务实现。

【问题讨论】:

  • 您是在客户端还是服务器上得到异常?生成的客户端代码里面有KnownTypeAttribute吗?
  • 服务器抛出异常。我已将 KnownTypeAttribute 添加到 ClientClass
  • 事实证明,在protracted but fruitful Q&A on chat :) 之后,基本问题是在回调合约中使用object 作为参数类型。客户端不知道如何反序列化自定义类型,所以KnownTypeAttribute 必须在某个地方出现。 @yas4891,你最后是怎么解决的?您现在有DataContract- 和KnownType- 标记的参数类型吗?不妨写出你的解决方案作为答案。
  • 我将object 更改为TransmissionClass 并将KnownType 应用于实现ClientInterface 的类。请写一个答案,你会得到这个学分

标签: c# .net wcf callback


【解决方案1】:

一般来说,反序列化参数或返回值的任何人(服务器或客户端)都需要知道在运行时期望什么类型(而不是合同)才能这样做。在这种情况下,object 类型的声明参数不会为客户端提供足够的信息来反序列化服务器可能发送回给它的任何内容。用 supported by the DataContractSerializer 类型替换它(如果服务器计划在回调中发送子类实例,则用 [KnownType] 装饰)解决了这个问题。

您也可以使用 configuration 告诉 DataContractSerializer 已知类型,但这是应用程序范围内的,对我来说似乎有点生硬。

我曾经遇到过一个不起眼的案例,我的合同看起来像这样:

[ServiceContract]
interface ISearch
{
    [OperationContract]
    SearchResult Search(SearchQuery query);
}

[DataContract]
[KnownType(typeof(Subclass1InSharedAssembly)), etc...]
class SearchResult
{
    [DataMember]
    BaseClassDeclaredInSharedAssembly Value { get; set; }
}

因为我希望服务器和客户端使用(有用的)共享程序集类型,所以我在两者中都有对共享程序集的引用,并选择不为它们生成任何代理类型......所以svcutil 没有t 为我生成任何KnownTypeAttributes。部分课程救了我的培根;在客户端上,你可以这样做:

// generated proxy .cs
[DataContract]
partial class SearchResult
{
    ...
}

// hand-written .cs
[KnownType(typeof(Subclass1InSharedAssembly)), etc.]
partial class SearchResult
{
    // Now the client knows how to deserialise derived types.
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 2019-06-07
    • 2023-03-30
    • 2015-07-15
    • 2020-07-08
    • 1970-01-01
    相关资源
    最近更新 更多