代码之家  ›  专栏  ›  技术社区  ›  chilltemp

如何在WCF上实现继承的字典

  •  8
  • chilltemp  · 技术社区  · 16 年前

    我试图实现一个与WCF一起使用的字典。我的要求是:

    • 实际(私有变量或基数 类)类型等效于 词典
    • 比较器 = 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);
    

    结果:

    • 当我将MyDictionary作为ParameterClass之一传递时。数据。值元素,我收到一个丢失的KnownType异常。
    • 我可以在ResultClass中安全地返回MyDictionary,但它不再是我的类型。这只是一本词典,不能随意使用 MyDictionary .也比较= System.Collections.Generic.GenericEqualityComparer<string> ,不是我要找的不区分大小写的比较器。

    我要求的帮助要么是修复我失败的尝试,要么是用一种完全不同的方式来实现我提出的要求。任何解决方案都不应涉及将一本词典复制到另一本词典。

    谢谢

    4 回复  |  直到 16 年前
        1
  •  10
  •   jezell    16 年前

    将CollectionDataContract添加到Dictionary类:

    有关使用收集数据契约实现字典的更多信息,请查看此链接:

    http://msdn.microsoft.com/en-us/library/aa347850.aspx

        2
  •  1
  •   Marc Gravell    16 年前

    序言:注意添加“新” Add 这并不能阻止人们给老人打电话 添加 仅仅通过铸造。此外,就“墨西哥商品交易所”而言,这是一个非常模糊的数据合同——它需要如此开放吗?(很多 object 等等)

    第一:你错过了几个吗 [DataContract] / [DataMember] 标记在那里?特别地:

    • 结果类。值
    • 参数数据
    • 参数数据。值
    • 参数类。数据

    你能澄清一下吗 确切地 哪个版本的。NET你在用什么? DataContractSerializer 其他功能已通过服务包进行了调整。安装了3.5 SP1(这是我唯一能拿到的东西)后,它至少可以通过以下方式进行序列化和反序列化 DataContractSerializer (无WCF堆栈),以及正确的 添加 方法被调用。

    你能检查一下以下内容是否适用于你的本地版本吗?(它适用于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堆栈),但它似乎可以工作……所以:相同的代码是否适用于您的本地版本。网?如果没有,是否可以选择安装最新的3.0 service pack?(最好是通过安装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>
    
        3
  •  1
  •   chilltemp    16 年前
    • 使用 CollectionDataContract 杰泽尔建议的属性
    • 使用/collectionType参数,使用SvcUtil手动生成引用(代理)代码。vs2008服务参考GUI不支持此参数。

    来源: WCF Collection Type Sharing

        4
  •  1
  •   lokusking    9 年前

    我终于找到了一种方法。我发现了 this link 这指向了正确的方向,但我会尽量总结一下。

    1. 请确保添加 [CollectionDataContract] 到您的定制收藏
    2. 像往常一样通过VS添加服务引用
    3. 展开服务引用并查找reference.svcmap文件
    4. 在客户端选项节点下,您将看到

    <集合映射/>

    用以下xml替换它。

    <集合映射>
    <CollectionMapping TypeName=“完整命名空间。此处”Category=“列表”/>
    </集合映射>

    1. 右键单击服务参考,然后单击更新。它不应该再生成“代理”类,而是允许您使用共享类。