Domanda

Ho un tipo, chiamiamolo Data<TKey>. Ho anche un contratto di servizio WCF che accetta un tipo (permette di chiamare Wrapper), con una proprietà di tipo Object (per ragioni che non andrà in, questo non è opzionale).

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

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

In questo momento sto inviando due classi IntData e LongData:

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

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

Sono entrambi configurati nei tipi noti file di configurazione. La configurazione assomiglia a qualcosa di simile:

<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 questo punto, tutto funziona bene.

Ma io sto per aggiungere un terzo tipo e non mi piace avere il superfluo, vuoto NET classi IntData e LongData. Esistono solo perché ...

non so come specificare tipi generici nella configurazione WCF!

Io voglio fare qualcosa di simile, ma non conosco la sintassi esatta.

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

Qual è la sintassi corretta per questo?

(Si noti anche che non posso mettere gli attributi [KnownType(...)] su Wrapper dato che non è il mio tipo. Config sembra essere l'unico modo.)

Modifica

@ risposta di Baretta ha funzionato bene. Si noti, tuttavia, che inizialmente ho ricevuto questo errore:

  

Tipo 'MyAssembly.Data`1 [System.Int64]' non può essere aggiunto alla lista dei tipi conosciuti dal un altro tipo 'MyAssembly.Data`1 [System.Int32]' con lo stesso nome del contratto di dati ' http://www.mycompany.com/MyAssembly:Data ' è già presente.

Non ho menzionarlo nella domanda iniziale, ma il mio tipo ha un nome esplicito contratto di dati. Qualcosa di simile a questo:

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

Si è verificato l'errore sopra finché ho rimosso il valore della proprietà Name dall'attributo. Speranza che aiuta qualcun altro troppo. Non so quale formato funziona in questo scenario. Questi non ha fatto:

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

Qualcuno sa come fare questo?

Modifica 2

Grazie ancora a @baretta che ha sottolineato che la sintassi corretta è in realtà:

[DataContract(Name = "Data{0}")]
È stato utile?

Soluzione

Un tipo generico è instanziabile da una stringa, se la stringa segue questo schema: Nome classe seguito da un carattere "`", seguito dal numero di parametri di tipo (in questo caso si tratta di 1), seguito dai parametri di tipo racchiusi all'interno di "[]", e usando la virgola come separatore di parametri di 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>

Modifica:. Potrei anche aggiungere, che se le informazioni di montaggio deve essere specificato per i parametri di tipo (althoug non è il caso di roba in mscorlib), quindi nidificato "[]" viene utilizzato

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

Modifica:. È possibile personalizzare i nomi dei tipi generici in contratti dati, utilizzando il modello formato di stringa

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

Per impostazione predefinita, il nome generato per il tipo di dati è qualcosa di simile "DataOfInt32HJ67AK7Y", dove "HJ67AK7Y" è un hash generato dalla stringa "urn: default", o lo spazio dei nomi della classe, se ne avete. Ma "dati {0}" avrebbe dato il nome di "DataInt32".

qui . Date un'occhiata alla parte "Personalizzazione dei dati nomi contratto per i tipi generici" in basso nella pagina.

Altri suggerimenti

qui ...

  

Noto   tipi possono essere definiti anche in config come   illustrato di seguito.

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

È possibile che questo config specifica che il   parametro generico per Circle è il   uguale al parametro generico per la   Forma tipo dichiarato. La configurazione permette   la definizione di tipo noto di   complessità arbitraria. Per esempio, se   è necessario definire   Circle > come il   tipo noto di Figura (ovviamente questo   è puramente accademico) si può fare come   segue.

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

Si noti l'uso elemento di configurazione   “Parametro” con ‘tipo’ gli attributi   e ‘index’.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top