Question

J'ai un type, nous allons l'appeler Data<TKey>. J'ai aussi un contrat de service WCF qui accepte un type (permet de l'appeler Wrapper) avec une propriété de type Object (pour des raisons que je ne rentrerais pas, ce n'est pas en option).

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

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

En ce moment, j'envoie deux classes IntData et LongData:

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

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

Ils sont tous les deux configurés dans le fichier de configuration types connus. La configuration ressemble à quelque chose comme ceci:

<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>

A ce moment, tout fonctionne très bien.

Mais je suis sur le point d'ajouter un troisième type et je n'aime pas avoir les classes .NET inutile, vide IntData et LongData. Ils existent seulement parce que ...

Je ne sais pas comment spécifier les types génériques dans la configuration de WCF!

Je veux faire quelque chose comme ça, mais je ne sais pas la syntaxe exacte.

<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>

Quelle est la syntaxe correcte pour cela?

(Notez aussi que je ne peux pas mettre [KnownType(...)] les attributs sur Wrapper que ce n'est pas mon genre. Config semble être la seule façon.)

EDIT

@ réponse Baretta fonctionnait bien. Notez cependant que d'abord j'ai reçu cette erreur:

  

Type 'MyAssembly.Data`1 [System.Int64]' ne peut pas être ajouté à la liste des types connus depuis un autre type 'MyAssembly.Data`1 [System.Int32]' avec le même nom de contrat de données « http://www.mycompany.com/MyAssembly:Data » est déjà présent.

Je ne l'ai pas le mentionner dans la question initiale, mais mon type a un nom de contrat de données explicites. Quelque chose comme ceci:

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

L'erreur ci-dessus a eu lieu jusqu'à ce que je retiré la valeur de la propriété Name de l'attribut. Hope qui aide quelqu'un d'autre aussi. Je ne sais pas quel format fonctionne dans ce scénario. Ceux-ci n'a pas:

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

Quelqu'un sait comment faire cela?

EDIT 2

Merci encore à @baretta qui a fait remarquer que la syntaxe correcte est en fait:

[DataContract(Name = "Data{0}")]
Était-ce utile?

La solution

Un type générique est instanciable d'une chaîne, si la chaîne suit ce modèle: Nom de la classe suivi d'un « ` » caractère, suivi par le nombre de paramètres de type (dans ce cas, il est 1), suivi des paramètres de type enfermés dans « [] », et en utilisant la virgule comme séparateur de paramètre de type .

<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>

Modifier. Je pourrais aussi ajouter que si l'information de montage doit être spécifié pour les paramètres de type (althoug ce n'est pas le cas pour les choses dans mscorlib), puis imbriqué « [] » est utilisé

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

Modifier. Vous pouvez personnaliser les noms des types génériques dans les contrats de données, en utilisant le modèle de format de chaîne

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

Par défaut, le nom généré pour le type de données est quelque chose comme « DataOfInt32HJ67AK7Y », où « HJ67AK7Y » est un hachage généré à partir de la chaîne « urn: default », ou l'espace de noms de votre classe, si vous en avez. Mais "données {0}" lui donnerait le nom "DataInt32".

En savoir plus . Jetez un oeil à la partie « Personnalisation des noms de contrat de données pour les types génériques » en bas de la page.

Autres conseils

De ...

  

Connue   types peuvent également être définis dans la configuration comme   ci-dessous.

<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 configuration ci-dessus indique que le   paramètre générique Circle est le   même que le paramètre générique pour la   type déclaré Forme. La configuration permet   la définition d'un type connu de   complexité arbitraire. Par exemple, si   il est nécessaire de définir   Cercle > comme   type connu de forme (bien sûr ce   est purement académique), il peut se faire que   suit.

<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>
  

Notez l'élément de configuration utilisé   « Paramètre » avec du type "les attributs   et « index ».

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top