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
The process forms a sequence of bytes into a logical object; this is called an encoding process. At runtime when WCF receives the logical message, it transforms them back into corresponding . Net objects. This process is called serialization.
This code constructs an instance of the DataContractSerializer that can be used only to serialize or deserialize instances of the Person class. DataContractSerializer dcs = new DataContractSerializer(typeof(Person)); // This can now be used to serialize/deserialize Person but not PurchaseOrder.
By default WCF uses the DataContractSerializer class to serialize data types.
If you expect the service to accept and return an inherited type then we use the knowntype attribute.
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
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>
CollectionDataContract
attribute as jezell suggestedSource: WCF Collection Type Sharing
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With