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

本文关键字:继承 字典 实现 WCF | 更新日期: 2023-09-27 17:48:49

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

  • 实际(私有变量或基数class)类型等效于词典
  • 比较器=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.Data.Value元素之一传递时,我会得到一个丢失的KnowType异常
  • 我可以安全地在ResultClass中返回MyDictionary,但它不再是我的类型。它只是一个Dictionary,不能转换为MyDictionary。还有comparer=System.Collections.Generic.GenericEqualityComparer<string>,而不是我要找的不区分大小写的comparer

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

感谢

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

将CollectionDataContract添加到Dictionary类:

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

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

序言:请注意,添加一个"新"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 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>
  • 按照jezell的建议使用CollectionDataContract属性
  • 使用/collectionType参数,使用SvcUtil手动生成引用(代理)代码。vs2008服务引用GUI不支持此参数

来源:WCF集合类型共享

我终于找到了一种方法。我发现这个链接指向了正确的方向,但我将尝试进行总结。

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

<集合映射/>

将其替换为以下xml。

<集合映射>
 nbsp<CollectionMapping TypeName="Full.Namespace.Here"Category="List"/>
<集合映射>

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