Pregunta

Tengo un tipo, vamos a llamarlo Data<TKey>. También tengo un contrato de servicio WCF que acepta un tipo (permite llamarlo Wrapper) con una propiedad de tipo Object (por razones que no voy a entrar, esto no es opcional).

[DataContract]
public class Data<TKey> { ... }

[DataContract]
public class Wrapper
{
    [DataMember]
    public object DataItem { get; set; }
}

En este momento estoy enviando dos clases IntData y LongData:

[DataContract]
public class IntData : Data<int> { /*empty*/ }

[DataContract]
public class LongData : Data<long> { /*empty*/ }

Están configurados tanto en los tipos conocidos fichero de configuración. La configuración se asemeja a algo como esto:

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="Wrapper, TheirAssembly">
          <knownType type="IntData, MyAssembly"/>
          <knownType type="LongData, MyAssembly"/>
        </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>

En este punto, todo funciona bien.

Pero estoy a punto de añadir un tercer tipo y no me gusta tener lo innecesario, vacío y clases IntData LongData .NET. Sólo existen porque ...

No sé cómo especificar los tipos genéricos en la configuración de WCF!

Quiero hacer algo como esto, pero no sé la sintaxis exacta.

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="Wrapper, TheirAssembly">
          <!-- this syntax is wrong -->
          <knownType type="Data{System.Int32}, MyAssembly"/>
          <knownType type="Data{System.Int64}, MyAssembly"/>
        </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>

¿Cuál es la sintaxis correcta para esto?

(Nota también que no puedo poner los atributos [KnownType(...)] en Wrapper ya que no es mi tipo. Config parece ser la única manera.)

Editar

@ respuesta de baretta funcionó muy bien. Sin embargo, nótese que en un principio he recibido este error:

  

Tipo 'MyAssembly.Data`1 [System.Int64]' no puede ser añadido a la lista de tipos conocidos desde otro tipo 'MyAssembly.Data`1 [System.Int32]' con el mismo nombre de contrato de datos ' http://www.mycompany.com/MyAssembly:Data ' ya está presente.

Yo no lo mencionó en la pregunta original, pero mi tipo tiene un nombre de contrato de datos explícita. Algo como esto:

[DataContract(Name = "Data")]
public class Data<TKey> { ... }

Se ha producido el error anterior hasta Quité el valor de la propiedad Name del atributo. Esperamos que ayuda a otra persona demasiado. No sé qué formato funciona en este escenario. Estos no lo hizo:

[DataContract(Name = "Data\`1")]
[DataContract(Name = "Data{TKey}")]

Alguien sabe cómo hacer esto?

EDIT 2

Gracias de nuevo a @baretta quien señaló que la sintaxis correcta es, de hecho:

[DataContract(Name = "Data{0}")]
¿Fue útil?

Solución

Un tipo genérico es crear instancias de una cadena, si la cadena sigue este patrón: Nombre de clase seguido de un "`" carácter, seguido por el número de parámetros de tipo (en este caso es 1), seguido de los parámetros de tipo encerrados dentro de "[]", y el uso de una coma como separador parámetro de tipo .

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="Wrapper, TheirAssembly">
          <!-- this syntax is all good -->
          <knownType type="Data`1[System.Int32], MyAssembly"/>
          <knownType type="Data`1[System.Int64], MyAssembly"/>
        </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>

Editar:. Podría añadir también, que si necesita ser especificado para los parámetros de tipo (althoug que no es el caso para la materia en mscorlib) información de ensamblado, a continuación, anidado "[]" se utiliza

<knownType type="Data`1[[System.Int32, mscorlib]], MyAssembly"/>

Editar:. Usted puede personalizar los nombres de los tipos genéricos de contratos de datos, utilizando el patrón de formato de cadena

[DataContract(Name = "Data{0}")]
public class Data<TKey>
{...}

Por defecto, el nombre generado por el Tipo de datos es algo así como "DataOfInt32HJ67AK7Y", donde "HJ67AK7Y" es un hash generado a partir de la cadena "urn: por defecto", o el espacio de nombres de la clase, si tiene alguno. Sin embargo, "datos {0}" le daría el nombre de "DataInt32".

aquí . Echar un vistazo a la parte de "Personalización de los datos del contrato nombres para tipos genéricos" en la página.

Otros consejos

aquí ...

  

Conocido   tipos también se pueden definir en config como   se muestra a continuación.

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
         <add type="MyCompany.Library.Shape`1,
              MyAssembly, Version=2.0.0.0, Culture=neutral,
              PublicKeyToken=XXXXXX, processorArchitecture=MSIL">
            <knownType type="MyCompany.Library.Circle`1,
                       MyAssembly, Version=2.0.0.0, Culture=neutral,
                       PublicKeyToken=XXXXXX, processorArchitecture=MSIL">
                    <parameter index="0"/>
            </knownType>
         </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>
  

La configuración anterior especifica que el   parámetro genérico para círculo es el   mismo que el parámetro genérico para el   Forma tipo declarado. La configuración permite   la definición de un tipo conocido de   complejidad arbitraria. Por ejemplo, si   es necesario definir   Círculo > como el   tipo conocido de Forma (por supuesto esto   es puramente académico) se puede hacer tan   de la siguiente manera.

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
         <add type="MyCompany.Library.Shape`1,
              MyAssembly, Version=2.0.0.0, Culture=neutral,
              PublicKeyToken=XXXXXX, processorArchitecture=MSIL">
            <knownType type="MyCompany.Library.Circle`1,
                       MyAssembly, Version=2.0.0.0, Culture=neutral,
                       PublicKeyToken=XXXXXX, processorArchitecture=MSIL">
                   <parameter type="System.Collections.Generic.Dictionary`2">
                      <parameter type="System.String"/>
                      <parameter index="0"/>
                   </parameter>                
            </knownType>
         </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>
  

Tenga en cuenta el elemento de uso de config   “Parámetro” con el ‘tipo’ de los atributos   e ‘índice’.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top