2015-12-16 179 views
2

我想通過WCF上的Dictionary屬性傳遞一個類,但它失敗了一個方法,但爲另一個方法工作。當班級在List內返回時,它可以工作。但是當班級返回DataTable時,客戶端只是說連接已斷開,並且沒有顯示錯誤。無法序列化System.Collections.Generic.Dictionary`2類型的成員......因爲它實現了IDictionary

這裏是類引起的問題:

[DataContract] 
public class DetailLog 
{ 
    [DataMember] 
    public string Name 
    { 
     get; 
     set; 
    } 

    [DataMember] 
    public string SubAction 
    { 
     get; 
     set; 
    } 

    [DataMember] 
    public Dictionary<string, string> Fields 
    { 
     get; 
     set; 
    } 

    [DataMember] 
    public string UserName 
    { 
     get; 
     set; 
    } 
} 

我開始了創建無問題工作的方法:

public List<DetailLog> GetDetailLog(List<int> IDs, List<int> actionTypeIds, List<int> userIds, DateTime beginDate, DateTime endDate) 

然後,我們需要創建一些非常動態的報道,所以我用一個DataTable我們以前用於其他動態報告。

但我還需要沿着DetailLog類傳遞,所以我創建了一個類型的數據表列:

public DataTable GetCustomDetailReport(int CustomReportID, List<CustomReportFilter> reportFilters) 
{ 
DataTable data = new DataTable(); 
... 
data.Columns.Add("DetailLog", typeof(DetailLog)); 
... 
} 

此方法將將退出精細的WCF主機端,但客戶端將錯誤有關連接正在失去。我嘗試添加ServiceKnownType在接口OperationContract的,但它並沒有解決它:

[OperationContract] 
[ServiceKnownType(typeof(DetailLog))] 
DataTable GetCustomUserAuditReport(int CustomReportID, List<CustomReportFilter> reportFilters); 

我真的不能調試序列化時,該方法返回的DataTable,所以我說這個代碼到GetCustomDetailReport結束()來趕上錯誤。

DataContractSerializer ser = new DataContractSerializer(typeof(DataTable), new List<Type> { typeof(DetailLog) }); 
ser.WriteObject(Stream.Null, data); 

當我做到了,我看到了一個異常

Cannot serialize member ... of type System.Collections.Generic.Dictionary`2 because it implements IDictionary. 

回答

2

你的問題如下:

  1. Dictionary<TKey, TValue>由WCF使用的data contract serializer支持,如在docs中解釋。這就是爲什麼您的DetailLog類可以通過WCF作爲根對象成功發送的原因。

  2. 該串行器還支持IXmlSerializable以允許類型將自己手動序列化爲XML。

  3. DataTable實施IXmlSerializable

  4. 在內部,DataTable串行化非原始條目使用XmlSerializer - 使用一個完全不同的代碼庫完全不同的序列化器。

  5. XmlSerializer does not support dictionaries。因此,當嵌套在DataTable中時,WCF 不能通過電線發送您的DetailLog

  6. 到無關的問題,還需要設置數據表名,如果你不序列化將拋出一個異常:

    data.TableName = "CustomDetailReport"; // For instance 
    

要解決的問題有字典,你需要讓你的DetailLog類可以由兩個序列化器串行化。問題How to serialize/deserialize to Dictionary<int, string> from custom XML not using XElement?給出了各種不同的方式序列化它的字典屬性,包括使用代理服務器陣列特性:

[XmlType("KeyValue"), XmlRoot("KeyValue")] 
public class SerializableKeyValuePair<TKey, TValue> 
{ 
    public TKey Key { get; set; } 
    public TValue Value { get; set; } 
} 

public static class SerializableKeyValuePairExtensions 
{ 
    public static SerializableKeyValuePair<TKey, TValue> ToSerializablePair<TKey, TValue>(this KeyValuePair<TKey, TValue> pair) 
    { 
     return new SerializableKeyValuePair<TKey, TValue> { Key = pair.Key, Value = pair.Value }; 
    } 
} 

[DataContract] 
public class DetailLog 
{ 
    [DataMember] 
    public string Name { get; set; } 

    [DataMember] 
    public string SubAction { get; set; } 

    [DataMember] 
    [XmlIgnore] 
    public Dictionary<string, string> Fields { get; set; } 

    [IgnoreDataMember] 
    [XmlArray("Fields")] 
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)] 
    public SerializableKeyValuePair<string, string>[] FieldsArray 
    { 
     get 
     { 
      return Fields == null ? null : Fields.Select(p => p.ToSerializablePair()).ToArray(); 
     } 
     set 
     { 
      Fields = value == null ? null : value.ToDictionary(p => p.Key, p => p.Value); 
     } 
    } 

    [DataMember] 
    public string UserName { get; set; } 
} 

WCF現在應該能夠在您的DataTable通過網絡發送成功。

+0

謝謝你這麼詳細的解釋! – sean

相關問題