如何通过WCF实现inheritance的Dictionary
我正在尝试实现一个用于WCF的字典。 我的要求是:
- 实际(私有变量或基类)类型等同于Dictionary
- Comparer =
System.StringComparer.InvariantCultureIgnoreCase
- 自定义(覆盖/新)添加(键,值)方法(包括validation)。
- 覆盖ToString()
- 在客户端和主机上使用相同类型
我试图在WCF主机和客户端项目共享的公共项目中使用此类:
[Serializable] public class MyDictionary : Dictionary { 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 Data{ get; set; } /* More properties */ } [OperationContract] ResultClass DoSomething(ParameterClass args);
结果:
- 当我将MyDictionary作为ParameterClass.Data.Value元素之一传递时,我得到一个缺少的KnownTypeexception。
- 我可以安全地在ResultClass中返回MyDictionary,但它不再是我的类型。 它只是一个字典,不能转换为
MyDictionary
。 另外comparer =System.Collections.Generic.GenericEqualityComparer
,而不是我正在寻找的不区分大小写的比较器。
我要求的帮助是要么修复我失败的尝试,要么是完全不同的方式来达到我声明的要求。 任何解决方案都不应涉及将一个字典复制到另一个
谢谢
将CollectionDataContract添加到Dictionary类:
有关使用集合数据协定实现字典的更多信息,请查看以下链接:
序言:请注意,添加“新” 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 { 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 pair in d) { Console.WriteLine("{0}={1}", pair.Key, pair.Value); } }
显然这只是测试DataContractSerializer
(没有整个WCF堆栈),但它似乎工作……所以:相同的代码是否适用于您的本地.NET版本? 如果没有,是否安装最新的3.0 Service Pack? (理想情况下通过安装3.5 SP1)。
有关信息,我得到xml:
abc 123 def ghi
- 使用
CollectionDataContract
属性作为jezell建议 - 使用/ collectionType参数使用SvcUtil手动生成引用(代理)代码。 vs2008服务引用GUI不支持此参数。
来源: WCF集合类型共享
我终于找到了办法。 我发现这个链接指向正确的方向,但我会尝试总结。
- 确保将
[CollectionDataContract]
添加到自定义集合中 - 像往常一样通过VS添加服务引用
- 展开服务引用并查找Reference.svcmap文件
- 在客户端选项节点下,您将看到
将其替换为以下xml。
CollectionMappings>
- 右键单击“服务引用”,然后单击“更新”。 它不应再生成“代理”类,并允许您使用共享类。