wfc crear c# wcf c#-3.0

c# - crear - Cómo implementar un diccionario heredado sobre WCF



crear wcf service c# (4)

Estoy tratando de implementar un diccionario para usar con WCF. Mis requisitos son:

  • tipo real (variable privada o clase base) equivalente a Dictionary
  • Comparer = System.StringComparer.InvariantCultureIgnoreCase
  • Método personalizado (anular / nuevo) Agregar (clave, valor) (para incluir validaciones).
  • Anular ToString ()
  • Uso del mismo tipo tanto en el cliente como en el host

Intenté usar esta clase en un proyecto común compartido por los proyectos de host y cliente de 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);

Resultados:

  • Cuando paso MyDictionary como uno de los elementos ParameterClass.Data.Value, me sale una excepción KnownType faltante.
  • Puedo devolver MyDictionary de forma segura en la clase ResultClass, pero ya no es mi tipo. Es solo un diccionario y no se puede MyDictionary en MyDictionary . También comparer = System.Collections.Generic.GenericEqualityComparer<string> , no es el comparador insensible a mayúsculas y minúsculas que estoy buscando.

La ayuda que estoy pidiendo es corregir mi intento fallido o una forma completamente diferente de cumplir mis requisitos establecidos. Cualquier solución no debería implicar copiar un diccionario a otro.

Gracias



Preámbulo: tenga en cuenta que agregar un "nuevo" Add no detiene a las personas que llaman al antiguo Add simplemente por conversión. Además, en términos de "mex", es un contrato de datos muy vago: ¿necesita ser tan abierto? (muchos object etc.)

Primero: ¿no te has perdido algunos marcadores [DataContract] / [DataMember] allí? En particular:

  • ResultClass.Value
  • ParamData
  • ParamData.Value
  • ParameterClass.Data

¿Puedes aclarar exactamente qué versión de .NET estás usando? DataContractSerializer etc ha sido ajustado a través de service packs. Con 3.5 SP1 instalado (lo único que tengo a mano) al menos se serializa y deserializa a través de DataContractSerializer (sin pila WCF), y se llama al método Add correcto.

¿Puedes verificar si lo siguiente funciona con tu versión local? (Funciona para mí con 3.5 SP1 y con los atributos que faltan) [output first]:

1 MyDictionary abc=123 def=ghi

Código:

// 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); } }

Obviamente, esto solo prueba DataContractSerializer (sin toda la pila de WCF), pero parece funcionar ... entonces, ¿funciona el mismo código con su versión local de .NET? De lo contrario, ¿es la instalación del último paquete de servicios 3.0 una opción? (idealmente mediante la instalación de 3.5 SP1).

Para obtener información, obtengo 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>


  • Utilice el atributo CollectionDataContract como se sugirió jezell
  • Genere manualmente el código de referencia (proxy) con SvcUtil, utilizando el parámetro / collectionType. Este parámetro no es compatible con la GUI de referencia del servicio vs2008.

Fuente: Uso compartido de la colección WCF


Finalmente encontré la manera de hacer esto. Encontré este enlace que apuntaba en la dirección correcta, pero intentaré resumirlo.

  1. Asegúrese de agregar [CollectionDataContract] a su colección personalizada
  2. Agregue referencia de servicio a través de VS como lo hace normalmente
  3. Expanda la referencia de servicio y busque el archivo Reference.svcmap
  4. Debajo del nodo de opciones del cliente verás

<CollectionMappings />

Reemplácelo con el siguiente xml.

<CollectionMappings>
<CollectionMapping TypeName = "Full.Namespace.Here" Categoría = "Lista" />
</ CollectionMappings>

  1. Haga clic derecho en la Referencia del servicio y haga clic en actualizar. Ya no debería generar esa clase de "proxy" y le permitirá usar su clase compartida.