Reputation: 8962
I’m trying to implement a dictionary for use with WCF. My requirements are:
System.StringComparer.InvariantCultureIgnoreCase
I’ve attempted using this class in a common project shared by the WCF host and client projects:
[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);
Results:
MyDictionary
. Also comparer = System.Collections.Generic.GenericEqualityComparer<string>
, not the case insensitive comparer I’m looking for.The help I’m asking for is to either fix my failed attempt, or a completely different way to achieve my stated requirements. Any solution should not involve copying one dictionary to another.
Thanks
Upvotes: 8
Views: 12535
Reputation: 10008
I finally found a way to do this. I found this link that pointed in the right direction but I will try to summarize.
[CollectionDataContract]
to your custom collection<CollectionMappings/>
Replace it with the following xml.
<CollectionMappings>
<CollectionMapping TypeName="Full.Namespace.Here" Category="List" />
</CollectionMappings>
Upvotes: 1
Reputation: 8962
CollectionDataContract
attribute as jezell suggestedSource: WCF Collection Type Sharing
Upvotes: 1
Reputation: 2532
Add CollectionDataContract to the Dictionary class:
For more information on using collection data contracts to implement dictionaries, check this link:
http://msdn.microsoft.com/en-us/library/aa347850.aspx
Upvotes: 10
Reputation: 1062492
Preamble: note that adding a "new" Add
doesn't stop people calling the old Add
simply by casting. Also, in terms of "mex", that is a very vague data-contract - does it need to be so open-ended? (lots of object
etc...)
First: haven't you missed a few [DataContract]
/[DataMember]
markers there? In particular:
Can you clarify exactly which version of .NET you are using? DataContractSerializer
etc have been tweaked via service packs. With 3.5 SP1 installed (the only thing I have to hand) it does at least serialize and deserialize via DataContractSerializer
(no WCF stack), and the correct Add
method is called.
Can you check whether the following works with your local version? (it works for me with 3.5 SP1 and with the missing attributes) [output first]:
1
MyDictionary
abc=123
def=ghi
Code:
// 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);
}
}
Obviously this just tests DataContractSerializer
(without the entire WCF stack), but it seems to work... so: does the same code work with your local version of .NET? If not, is installing the latest 3.0 service pack an option? (ideally via installing 3.5 SP1).
For info, I get 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>
Upvotes: 1