Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Das DataContract-Beispiel veranschaulicht, wie Prozesse wie Serialisierung, Deserialisierung, Schemaexport und Schemaimport mithilfe einer Datenvertrags-Surrogateklasse angepasst werden können. In diesem Beispiel wird gezeigt, wie Sie ein Ersatz in einem Client- und Serverszenario verwenden, in dem Daten serialisiert und zwischen einem WCF-Client und einem Dienst (Windows Communication Foundation) übertragen werden.
Hinweis
Die Einrichtungsverfahren und Build-Anweisungen für dieses Beispiel befinden sich am Ende dieses Themas.
Im Beispiel wird der folgende Dienstvertrag verwendet:
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
[AllowNonSerializableTypes]
public interface IPersonnelDataService
{
[OperationContract]
void AddEmployee(Employee employee);
[OperationContract]
Employee GetEmployee(string name);
}
Mit AddEmployee dem Vorgang können Benutzer Daten zu neuen Mitarbeitern hinzufügen, und der GetEmployee Vorgang unterstützt die Suche nach Mitarbeitern basierend auf dem Namen.
Diese Vorgänge verwenden den folgenden Datentyp:
[DataContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
class Employee
{
[DataMember]
public DateTime dateHired;
[DataMember]
public Decimal salary;
[DataMember]
public Person person;
}
In dem Employee Typ kann die Person Klasse (im folgenden Beispielcode dargestellt) nicht von der DataContractSerializer serialisiert werden, da es sich nicht um eine gültige Datenvertragsklasse handelt.
public class Person
{
public string firstName;
public string lastName;
public int age;
public Person() { }
}
Sie können das DataContractAttribute Attribut auf die Person Klasse anwenden, dies ist jedoch nicht immer möglich. Beispielsweise kann die Person Klasse in einer separaten Assembly definiert werden, über die Sie keine Kontrolle haben.
Angesichts dieser Einschränkung besteht eine Möglichkeit zum Serialisieren der Person-Klasse darin, sie durch eine andere Klasse zu ersetzen, die mit DataContractAttribute markiert ist, und die erforderlichen Daten in die neue Klasse zu kopieren. Das Ziel ist dabei, die Person-Klasse für DataContractSerializer als DataContract erscheinen zu lassen. Beachten Sie, dass dies eine Möglichkeit ist, Nicht-Daten-Vertragsklassen zu serialisieren.
Das Beispiel ersetzt die Person Klasse logisch durch eine andere Klasse mit dem Namen PersonSurrogated.
[DataContract(Name="Person", Namespace = "http://Microsoft.ServiceModel.Samples")]
public class PersonSurrogated
{
[DataMember]
public string FirstName;
[DataMember]
public string LastName;
[DataMember]
public int Age;
}
Zum Durchführen dieser Ersetzung wird das Datenvertrag-Ersatzzeichen verwendet. Ein Datenvertrags-Stellvertreter ist eine Klasse, die IDataContractSurrogate implementiert. In diesem Beispiel implementiert die AllowNonSerializableTypesSurrogate Klasse diese Schnittstelle.
In der Schnittstellenimplementierung besteht die erste Aufgabe darin, eine Typzuordnung von Person zu PersonSurrogated zu erstellen. Dies wird sowohl zur Serialisierungszeit als auch zur Schemaexportzeit verwendet. Diese Zuordnung wird durch die Implementierung der GetDataContractType(Type) Methode erreicht.
public Type GetDataContractType(Type type)
{
if (typeof(Person).IsAssignableFrom(type))
{
return typeof(PersonSurrogated);
}
return type;
}
Die GetObjectToSerialize(Object, Type) Methode ordnet eine Person Instanz während der Serialisierung einer PersonSurrogated Instanz zu, wie im folgenden Beispielcode gezeigt.
public object GetObjectToSerialize(object obj, Type targetType)
{
if (obj is Person)
{
Person person = (Person)obj;
PersonSurrogated personSurrogated = new PersonSurrogated();
personSurrogated.FirstName = person.firstName;
personSurrogated.LastName = person.lastName;
personSurrogated.Age = person.age;
return personSurrogated;
}
return obj;
}
Die GetDeserializedObject(Object, Type) Methode stellt die Umkehrzuordnung für die Deserialisierung zur Verfügung, wie im folgenden Beispielcode gezeigt.
public object GetDeserializedObject(object obj,
Type targetType)
{
if (obj is PersonSurrogated)
{
PersonSurrogated personSurrogated = (PersonSurrogated)obj;
Person person = new Person();
person.firstName = personSurrogated.FirstName;
person.lastName = personSurrogated.LastName;
person.age = personSurrogated.Age;
return person;
}
return obj;
}
Um den PersonSurrogated Datenvertrag während des Schemaimports der vorhandenen Person Klasse zuzuordnen, implementiert das Beispiel die GetReferencedTypeOnImport(String, String, Object) Methode, wie im folgenden Beispielcode dargestellt.
public Type GetReferencedTypeOnImport(string typeName,
string typeNamespace, object customData)
{
if (
typeNamespace.Equals("http://schemas.datacontract.org/2004/07/DCSurrogateSample")
)
{
if (typeName.Equals("PersonSurrogated"))
{
return typeof(Person);
}
}
return null;
}
Der folgende Beispielcode schließt die Implementierung der IDataContractSurrogate Schnittstelle ab.
public System.CodeDom.CodeTypeDeclaration ProcessImportedType(
System.CodeDom.CodeTypeDeclaration typeDeclaration,
System.CodeDom.CodeCompileUnit compileUnit)
{
return typeDeclaration;
}
public object GetCustomDataToExport(Type clrType,
Type dataContractType)
{
return null;
}
public object GetCustomDataToExport(
System.Reflection.MemberInfo memberInfo, Type dataContractType)
{
return null;
}
public void GetKnownCustomDataTypes(
KnownTypeCollection customDataTypes)
{
// It does not matter what we do here.
throw new NotImplementedException();
}
In diesem Beispiel wird der Ersatz im ServiceModel durch ein Attribut aktiviert, genannt AllowNonSerializableTypesAttribute. Entwickler müssen dieses Attribut auf ihren Servicevertrag anwenden, wie im IPersonnelDataService obigen Servicevertrag gezeigt. Dieses Attribut implementiert IContractBehavior und richtet das Ersatzzeichen bei Vorgängen in der ApplyClientBehavior-Methode und der ApplyDispatchBehavior-Methode ein.
Das Attribut ist in diesem Fall nicht erforderlich – es wird für Demonstrationszwecke in diesem Beispiel verwendet. Benutzer können alternativ einen Ersatz aktivieren, indem sie manuell einen ähnlichen IContractBehavior, IEndpointBehavior oder IOperationBehavior mithilfe von Code oder durch Konfiguration hinzufügen.
Die IContractBehavior Implementierung sucht nach Vorgängen, die DataContract verwenden, indem überprüft wird, ob sie ein DataContractSerializerOperationBehavior registriert haben. Wenn dies der Fall ist, wird die DataContractSurrogate-Eigenschaft auf dieses Verhalten festgelegt. Der folgende Beispielcode zeigt, wie dies erfolgt. Durch das Festlegen des Ersatzzeichens auf dieses Vorgangsverhalten wird es für die Serialisierung und die Deserialisierung aktiviert.
public void ApplyClientBehavior(ContractDescription description, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime proxy)
{
foreach (OperationDescription opDesc in description.Operations)
{
ApplyDataContractSurrogate(opDesc);
}
}
public void ApplyDispatchBehavior(ContractDescription description, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatch)
{
foreach (OperationDescription opDesc in description.Operations)
{
ApplyDataContractSurrogate(opDesc);
}
}
private static void ApplyDataContractSurrogate(OperationDescription description)
{
DataContractSerializerOperationBehavior dcsOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dcsOperationBehavior != null)
{
if (dcsOperationBehavior.DataContractSurrogate == null)
dcsOperationBehavior.DataContractSurrogate = new AllowNonSerializableTypesSurrogate();
}
}
Damit das Ersatzzeichen für die Verwendung bei der Metadaten-Generierung eingebunden werden kann, sind zusätzliche Schritte erforderlich. Ein Mechanismus, um dies zu erreichen, besteht darin, ein IWsdlExportExtension bereitzustellen, das in diesem Beispiel demonstriert wird. Eine weitere Möglichkeit besteht darin, die WsdlExporter direkt zu ändern.
Das AllowNonSerializableTypesAttribute Attribut implementiert IWsdlExportExtension und IContractBehavior. Die Erweiterung kann in diesem Fall entweder IContractBehavior oder IEndpointBehavior sein. Die Implementierung der IWsdlExportExtension.ExportContract-Methode aktiviert das Ersatzzeichen, indem es dem bei der Schemagenerierung für DataContract verwendeten XsdDataContractExporter hinzugefügt wird. Der folgende Codeausschnitt zeigt, wie dies funktioniert.
public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)
{
if (exporter == null)
throw new ArgumentNullException("exporter");
object dataContractExporter;
XsdDataContractExporter xsdDCExporter;
if (!exporter.State.TryGetValue(typeof(XsdDataContractExporter), out dataContractExporter))
{
xsdDCExporter = new XsdDataContractExporter(exporter.GeneratedXmlSchemas);
exporter.State.Add(typeof(XsdDataContractExporter), xsdDCExporter);
}
else
{
xsdDCExporter = (XsdDataContractExporter)dataContractExporter;
}
if (xsdDCExporter.Options == null)
xsdDCExporter.Options = new ExportOptions();
if (xsdDCExporter.Options.DataContractSurrogate == null)
xsdDCExporter.Options.DataContractSurrogate = new AllowNonSerializableTypesSurrogate();
}
Wenn Sie das Beispiel ausführen, ruft der Client AddEmployee gefolgt von einem GetEmployee-Aufruf auf, um zu überprüfen, ob der erste Anruf erfolgreich war. Das Ergebnis der GetEmployee-Vorgangsanforderung wird im Clientkonsolenfenster angezeigt. Der GetEmployee-Vorgang muss den Mitarbeiter finden und „found“ ausgeben.
Hinweis
In diesem Beispiel wird gezeigt, wie Sie einen Ersatz für Serialisieren, Deserialisieren und Metadatengenerierung einsetzen. Es wird nicht beschrieben, wie man einen Ersatz für die Codegenerierung aus Metadaten anschließt. Ein Beispiel für die Verwendung eines Ersatzzeichens zum Einbinden in die Clientcodegenerierung finden Sie im Beispiel Benutzerdefinierte WSDL-Veröffentlichung.
So können Sie das Beispiel einrichten, erstellen und ausführen
Stellen Sie sicher, dass Sie das One-Time Setup-Verfahren für die Windows Communication Foundation-Beispieleausgeführt haben.
Befolgen Sie zum Erstellen der C#-Edition der Lösung die Anweisungen zum Erstellen der Windows Communication Foundation-Beispiele.
Wenn Sie das Beispiel in einer Konfiguration mit einem Computer oder über Computer hinweg ausführen möchten, folgen Sie den Anweisungen unter Durchführen der Windows Communication Foundation-Beispiele.