Wie eine WCF bekannte Art in config angeben, die generisch ist?
-
13-09-2019 - |
Frage
ich einen Typ haben, nennen wir es Data<TKey>
. Ich habe auch einen WCF-Service-Vertrag haben, die eine Art akzeptiert (nennen wir es Wrapper
) mit einer Eigenschaft vom Typ Object
(aus Gründen, ich werde nicht gehen, dies ist nicht optional).
[DataContract]
public class Data<TKey> { ... }
[DataContract]
public class Wrapper
{
[DataMember]
public object DataItem { get; set; }
}
Im Moment Ich schicke zwei Klassen IntData
und LongData
:
[DataContract]
public class IntData : Data<int> { /*empty*/ }
[DataContract]
public class LongData : Data<long> { /*empty*/ }
Sie sind beide in den bekannten Arten konfiguriert Datei config. Die Konfiguration ähnelt etwas wie folgt aus:
<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>
An diesem Punkt alles funktioniert.
Aber ich bin über einen dritten Typ hinzuzufügen, und ich weiß nicht wie das unnötig, leer .NET-Klassen IntData
und LongData
haben. Sie bestehen nur, weil ...
Ich weiß nicht, wie generische Typen in WCF-Konfiguration angeben!
Ich mag so etwas wie dies zu tun, aber nicht wissen, die genaue Syntax.
<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>
Was ist die korrekte Syntax für das?
(Beachten Sie auch, dass ich nicht [KnownType(...)]
Attribute auf Wrapper
setzen kann, da es nicht meine Art ist. Config scheint der einzige Weg zu sein.)
Bearbeiten
@ baretta Antwort schön gearbeitet. Beachten Sie jedoch, dass zunächst ich diesen Fehler erhalten:
Typ ‚MyAssembly.Data`1 [System.Int64]‘ kann nicht zur Liste der bekannten Typen da eine andere Art hinzugefügt werden ‚MyAssembly.Data`1 [System.Int32]‘ mit dem gleichen Datenvertragsnamen ‚ http://www.mycompany.com/MyAssembly:Data ‘ist bereits vorhanden.
Ich habe es nicht in der ursprünglichen Frage erwähnen, aber meine Art hat einen expliziten Datenvertragsnamen. So etwas wie folgt aus:
[DataContract(Name = "Data")]
public class Data<TKey> { ... }
Der obige Fehler aufgetreten, bis ich den Name
Eigenschaftswert aus dem Attribute entfernt. Ich hoffe, dass auch jemand anderes heraus hilft. Ich weiß nicht, welches Format in diesem Szenario funktioniert. Dies tat nicht:
[DataContract(Name = "Data\`1")]
[DataContract(Name = "Data{TKey}")]
Wer weiß, wie dies zu tun?
EDIT 2
Danke nochmal an @baretta der darauf hinwies, dass die richtige Syntax in der Tat:
[DataContract(Name = "Data{0}")]
Lösung
Ein generischer Typ ist instantiable aus einem String, wenn die Zeichenfolge dieses Muster folgt: Klassenname von einem „`“Zeichen, gefolgt von der Anzahl der Parameter des Typs gefolgt (in diesem Fall ist es 1 ist), die durch die Parameter des Typs eingeschlossen innerhalb des„[]“gefolgt, und mit Komma als Typ-Parameter Separator .
<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>
Edit:. Ich könnte auch hinzufügen, dass, wenn Montageinformationen für die Typ-Parameter angegeben werden muss (althoug es für Sachen in mscorlib nicht der Fall ist), dann verschachtelt „[]“ verwendet wird,
<knownType type="Data`1[[System.Int32, mscorlib]], MyAssembly"/>
Edit:. Sie können Namen von generischen Typen in Datenverträge anpassen, die String-Format Muster mit
[DataContract(Name = "Data{0}")]
public class Data<TKey>
{...}
In der Standardeinstellung erzeugt der Name für die Daten
Mehr hier . Werfen Sie einen Blick auf die „Customizing Datenvertragsnamen für generische Typen“ Teil auf der Seite.
Andere Tipps
hier ...
Bekannte Typen können auch in Config wie folgt definiert werden unten gezeigt.
<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>
Die obige Config gibt an, dass die allgemeine Parameter für Kreis ist die gleiche wie der allgemeine Parameter für die deklarierten Typ-Form. Die Konfiguration erlaubt die Definition der bekannten Art von beliebige Komplexität. Zum Beispiel, wenn es benötigt wird, um zu definieren, Kreis
> als die bekannte Art von Form (natürlich dieser ist rein akademisch) es getan werden kann als folgt.
<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>
Beachten Sie die Verwendung config-Element „Parameter“ mit den ‚Typ‘ Attribute und ‚Index‘.