2008-11-05 49 views
7

我正在嘗試實現與WCF一起使用的字典。我的要求是:如何通過WCF實現繼承的字典

  • 實際(專用變量或基 類)類型相當於 字典
  • 的Comparer = System.StringComparer.InvariantCultureIgnoreCase
  • 自定義(倍率/新)添加(鍵, 值)方法(以包括 驗證)。
  • 覆蓋的ToString()
  • 客戶機和主機都

我在由WCF主機和客戶端項目共享的公共項目中使用這個類試圖在使用相同類型的:

[Serializable] 
public class MyDictionary : Dictionary<string, object> 
{ 
    public MyDictionary() 
    : base(System.StringComparer.InvariantCultureIgnoreCase) 
    { } 

    public new void Add(string key, object value) 
    { /* blah */ } 

    public override string ToString() 
    { /* blah */ } 
} 

[DataContract] 
[KnownType(typeof(MyDictionary))] 
[KnownType(typeof(object[]))] 
[KnownType(typeof(double[]))] 
[KnownType(typeof(string[]))] 
[KnownType(typeof(DateTime[]))] 
public class ResultClass 
{ 
    public object Value{ get; set; } 
    /* More properties */ 
} 
public class ParmData 
{ 
    public object Value{ get; set; } 
    /* More properties */ 
} 
[DataContract] 
[KnownType(typeof(MyDictionary))] 
[KnownType(typeof(object[]))] 
[KnownType(typeof(double[]))] 
[KnownType(typeof(string[]))] 
[KnownType(typeof(DateTime[]))] 
public class ParameterClass 
{ 
    public List<ParmData> Data{ get; set; } 
    /* More properties */ 
} 

[OperationContract] 
ResultClass DoSomething(ParameterClass args); 

結果:

  • 當我通過My​​Dictionary作爲ParameterClass.Data.Value元件中的一個,我GE缺少KnownType異常。
  • 我可以安全地返回ResultClass中的MyDictionary,但它不再是我的類型。它只是一個字典,不可鑄造成MyDictionary。還比較= System.Collections.Generic.GenericEqualityComparer<string>,而不是我要找的不區分大小寫的比較器。

我要求的幫助是要麼修復我失敗的嘗試,要麼完全不同的方式來達到我聲明的要求。任何解決方案都不應涉及將一本字典複製到另一個字典。

感謝

+0

是一個NetDataContractAttribute一個可行的選擇?也就是說,你能夠有保證可在客戶端和服務器端都與您的MyDictionary類相同的程序集的副本? – cfeduke 2008-11-06 02:33:16

+0

感謝您回覆我的文章 - 但您還沒有回答:我發佈的代碼是否適合您的設置?或者它是否拋出異常(或不將數據帶回)? – 2008-11-06 21:40:50

+0

馬克 - 我只有一次嘗試過你的測試。 clone.Data拋出一個空值異常。謝謝你的幫助,但是jezell指出了我的正確方向。 – chilltemp 2008-11-06 23:02:48

回答

1
  • 使用CollectionDataContract屬性作爲jezell建議
  • 手動生成與SvcUtil工具基準(代理)代碼,使用/ collectionType參數。 vs2008服務參考GUI不支持此參數。

來源:WCF Collection Type Sharing

1

序言:注意添加一個「新」 Add並不能阻止人們通過鑄造調用舊Add簡單。另外,就「mex」而言,這是一個非常模糊的數據合同 - 它是否需要如此開放? (很多object等...)

第一:你沒有錯過幾個[DataContract]/[DataMember]標記嗎?特別是:

  • ResultClass.Value
  • ParamData
  • ParamData.Value
  • ParameterClass.Data

你能澄清正是您正在使用的.NET版本? DataContractSerializer等已經通過服務包進行了調整。在安裝3.5 SP1(唯一需要處理的事情)時,它至少會通過DataContractSerializer(無WCF堆棧)序列化和反序列化,並調用正確的Add方法。

你能檢查下列版本是否適用於你的本地版本? (它適用於我3。5 SP1以及與缺少的屬性)輸出首頁]:

1 
MyDictionary 
abc=123 
def=ghi 

代碼:

 // or long-hand in C# 2.0 
     ParameterClass pc = new ParameterClass { 
      Data = new List<ParmData> { new ParmData { 
       Value = new MyDictionary { 
        {"abc",123}, 
        {"def","ghi"} 
       }}}}; 
     DataContractSerializer dcs = new DataContractSerializer(pc.GetType()); 
     string xml; 
     using(StringWriter sw = new StringWriter()) 
     using(XmlWriter xw = XmlWriter.Create(sw)) { 
      dcs.WriteObject(xw, pc); 
      xw.Close(); 
      xml = sw.ToString(); 
     } 
     using(StringReader sr = new StringReader(xml)) { 
      ParameterClass clone = (ParameterClass)dcs.ReadObject(XmlReader.Create(sr)); 
      Console.WriteLine(clone.Data.Count); 
      Console.WriteLine(clone.Data[0].Value.GetType().Name); 
      MyDictionary d = (MyDictionary)clone.Data[0].Value; 
      foreach (KeyValuePair<string, object> pair in d) 
      { 
       Console.WriteLine("{0}={1}", pair.Key, pair.Value); 
      } 
     } 

顯然,這只是測試DataContractSerializer(不含整個WCF棧),但它似乎工作...所以:相同的代碼是否與你的本地版本的.NET一起工作?如果沒有,是安裝最新的3.0服務包一個選項? (理想情況下通過安裝3.5 SP1)。

有關信息,我得到的xml:

<?xml version="1.0" encoding="utf-16"?><ParameterClass xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/"><Data><ParmData><Value xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:type="d4p1:ArrayOfKeyValueOfstringanyType"><d4p1:KeyValueOfstringanyType><d4p1:Key>abc</d4p1:Key><d4p1:Value xmlns:d6p1="http://www.w3.org/2001/XMLSchema" i:type="d6p1:int">123</d4p1:Value></d4p1:KeyValueOfstringanyType><d4p1:KeyValueOfstringanyType><d4p1:Key>def</d4p1:Key><d4p1:Value xmlns:d6p1="http://www.w3.org/2001/XMLSchema" i:type="d6p1:string">ghi</d4p1:Value></d4p1:KeyValueOfstringanyType></Value></ParmData></Data></ParameterClass> 
+0

安裝的.NET運行庫:1.0.3705.0版本1.0 RTM; 1.1.4322.2407版本1.1後SP1與KB928366; 2.0.50727.1433; 3.0.4506.648。 是的,合同必須是開放式的。這是一個遺留系統的包裝。 – chilltemp 2008-11-06 15:49:57

+0

但它工作? – 2008-11-06 21:41:22

1

我終於找到了一個辦法做到這一點。我發現this link,在正確的方向,但我會盡力來概括。

  1. 請務必添加[CollectionDataContract]到您的自定義集合
  2. 添加服務引用通過VS就像你通常做
  3. 展開服務引用和查找文件Reference.svcmap
  4. 在客戶機選項節點你會看到

< CollectionMappings />

與下面的XML替換它。

< CollectionMappings>
    < CollectionMapping類型名= 「Full.Namespace.Here」 類別= 「列表」/>
</CollectionMappings>

  • 右鍵單擊服務引用,並單擊更新。它不應該再生成這個「代理」類,並且會讓你使用你的共享類。