2014-03-31 38 views
1

首先,我希望我提供足夠的信息來弄清楚事情,如果不是請多詢問一下。WCF反序列化沒有已知類型

我有一個工作WCF通信使用雙工信道和OneWay方法調用。 ServiceHost位於使用NetPipeBinding的託管WPF應用程序中,客戶端位於該應用程序內的AppDomain中。只要所有類型都是原始類型(字符串,DateTime,...)或指定爲已知類型(List<object>,List<string>),一切都按預期工作。但我需要發送其他類型,爲此我不能添加已知的類型屬性,因爲在編譯時我不知道它們。

正如我在這裏閱讀(http://msdn.microsoft.com/library/ms731923(v=vs.100).aspx)所有具有公共屬性的公共類型都受支持,所以用SerializableAttribute裝飾的類型也是如此。

我試圖傳遞一個非常簡單的類:

public class ADT 
{ 
    public string Name { get; set; } 
} 

和作爲第二嘗試

[Serializable] 
public class SerializableADT 
{ 
    public string Name { get; set; } 
} 

和Herdo

[DataContract] 
public class DataContractADT 
{ 
    [DataMember] 
    public string Name { get; set; } 
    [DataMember] 
    public object Value { get; set; } 
} 

的建議,但反序列化的所有失敗三種類型。

嘗試序列化參數 _http://tempuri.org/:returnValue時發生錯誤。 InnerException消息是'類型 'TestLibraries.SeriablizableADT',數據協定名稱爲 'SeriablizableADT:_http://schemas.datacontract.org/2004/07/TestLibraries' 不是預期的。考慮使用DataContractResolver或將任何未知的 類型靜態添加到已知類型的列表中 - 例如,使用KnownTypeAttribute屬性的 或將其添加到傳遞給DataContractSerializer的已知類型的 列表中。有關更多詳細信息,請參閱 InnerException。

如何在沒有任何編譯時間變化的情況下編組符合MSDN規則的任何類型(例如用Serializable修飾)?

+0

您是否嘗試過'SerializeableADT'的'DataContract'屬性? – Herdo

+0

是的,我做了 - 但我得到了同樣的錯誤。我讀過Serializable和DataContract行爲相同,只要使用默認的DataContractSerializer。我正在嘗試DataContractResolver方法(來自異常消息) - 但仍然沒有運氣。 – thomek

回答

2

如果這是一個完全的內部服務,您可以切換到使用NetDataContractSerializer,它由包括全類型解決了這個問題,程序集信息(note該序列化程序徹底打破了互操作性和合同版本控制 - 因此請勿將其用於外部公開的服務)。沒有KnownType必要。要使用它,你需要一個行爲和一個屬性。您可以將以下屬性放在您的合同或單個操作上:

public class UseNetDataContractSerializerAttribute : Attribute, IOperationBehavior, IContractBehavior 
{ 
    void IOperationBehavior.ApplyClientBehavior(OperationDescription description, ClientOperation proxy) 
    { 
     ReplaceDataContractSerializerOperationBehavior(description); 
    } 

    void IOperationBehavior.ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch) 
    { 
     ReplaceDataContractSerializerOperationBehavior(description); 
    } 

    void IOperationBehavior.Validate(OperationDescription description) 
    { 
    } 

    void IOperationBehavior.AddBindingParameters(OperationDescription description, BindingParameterCollection parameters) 
    { 
    } 

    private static void ReplaceDataContractSerializerOperationBehavior(OperationDescription description) 
    { 
     var behavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>(); 

     if (behavior != null) 
     { 
      description.Behaviors.Remove(behavior); 
      description.Behaviors.Add(new NetDataContractSerializerOperationBehavior(description)); 
     } 
    } 

    void IContractBehavior.ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) 
    { 
     foreach (var operation in contractDescription.Operations) 
     { 
      ReplaceDataContractSerializerOperationBehavior(operation); 
     } 
    } 

    void IContractBehavior.ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
    { 
     foreach (var operation in contractDescription.Operations) 
     { 
      ReplaceDataContractSerializerOperationBehavior(operation); 
     } 
    } 

    void IContractBehavior.Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) 
    { 
    } 

    void IContractBehavior.AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
    { 
    } 
} 

public class NetDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior 
{ 
    public NetDataContractSerializerOperationBehavior(OperationDescription operation) 
     : base(operation) 
    { 
    } 

    public NetDataContractSerializerOperationBehavior(OperationDescription operation, DataContractFormatAttribute dataContractFormatAttribute) 
     : base(operation, dataContractFormatAttribute) 
    { 
    } 

    public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes) 
    { 
     return new NetDataContractSerializer(name, ns); 
    } 

    public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes) 
    { 
     return new NetDataContractSerializer(name, ns); 
    } 
} 
+1

非常感謝 - 這正是我正在尋找的! – thomek

+0

我不能稱讚你足夠以利。你的實用課是救生員。謝謝你的洞察力。 – xDisruptor