WCF:在回调中使用自定义类

时间:2011-06-21 19:15:23

标签: c# .net wcf callback

我设法使用字符串进行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服务实现。

1 个答案:

答案 0 :(得分:3)

通常,无论是谁(服务器或客户端)对参数或返回值进行反序列化,都需要知道在运行时期望的类型(而不是合同)。在这种情况下,类型为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没有为我生成任何KnownTypeAttribute个。部分课程保存了我的培根;在客户端上,您可以执行以下操作:

// 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.
}