Freigeben über


Verwenden eines Datenvertragsresolvers

Mithilfe eines Datenvertragsresolver können Sie bekannte Typen dynamisch konfigurieren. Bekannte Typen sind erforderlich, wenn ein Typ serialisiert oder deserialisiert wird, der von einem Datenvertrag nicht erwartet wird. Weitere Informationen zu bekannten Typen finden Sie unter Bekannte Typen in Datenverträgen. Bekannte Typen werden in der Regel statisch angegeben. Das bedeutet, dass Sie beim Implementieren eines Vorgangs alle möglichen Typen kennen müssen, die der Vorgang erhalten kann. In einigen Szenarios trifft dies nicht zu, und es ist wichtig, bekannte Typen dynamisch angeben zu können.

Erstellen eines Datenvertragsresolvers

Das Erstellen eines Datenvertragsresolvers umfasst die Implementierung von zwei Methoden: TryResolveType und ResolveName. Diese beiden Methoden implementieren Rückrufe, die jeweils während der Serialisierung und der Deserialisierung verwendet werden. Die TryResolveType-Methode wird während der Serialisierung aufgerufen. Sie verwendet einen Datenvertragstyp und ordnet diesen einem xsi:type-Namen und einem Namespace zu. Die ResolveName-Methode wird während der Deserialisierung aufgerufen. Sie verwendet einen xsi:type-Namen und einen Namespace und löst diesen zu einem Datenvertragstyp auf. Beide Methoden verfügen über einen knownTypeResolver-Parameter, der verwendet werden kann, um den standardmäßigen bekannten Typresolver in der Implementierung zu verwenden.

Im folgenden Beispiel wird gezeigt, wie Sie einen DataContractResolver implementieren, um die Zuordnung zu und von einem Datenvertragstyp mit dem Namen Customer vorzunehmen, der vom einem Datenvertragstyp Person abgeleitet wurde.

public class MyCustomerResolver : DataContractResolver  
{  
    public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)  
    {  
        if (dataContractType == typeof(Customer))  
        {  
            XmlDictionary dictionary = new XmlDictionary();  
            typeName = dictionary.Add("SomeCustomer");  
            typeNamespace = dictionary.Add("http://tempuri.com");  
            return true;  
        }  
        else  
        {  
            return knownTypeResolver.TryResolveType(dataContractType, declaredType, null, out typeName, out typeNamespace);  
        }  
    }  
  
    public override Type ResolveName(string typeName, string typeNamespace, DataContractResolver knownTypeResolver)  
    {  
        if (typeName == "SomeCustomer" && typeNamespace == "http://tempuri.com")  
        {  
            return typeof(Customer);  
        }  
        else  
        {  
            return knownTypeResolver.ResolveName(typeName, typeNamespace, null);  
        }  
    }  
}  

Nachdem Sie einen DataContractResolver definiert haben, können Sie diesen verwenden, indem Sie ihn an den DataContractSerializer-Konstruktor übergeben. Dies ist im folgenden Beispiel dargestellt.

XmlObjectSerializer serializer = new DataContractSerializer(typeof(Customer), null, Int32.MaxValue, false, false, null, new MyCustomerResolver());  

Sie können einen DataContractResolver in einem Aufruf der Methoden DataContractSerializer.ReadObject oder DataContractSerializer.WriteObject angeben, wie im folgenden Beispiel gezeigt.

MemoryStream ms = new MemoryStream();  
DataContractSerializer serializer = new DataContractSerializer(typeof(Customer));  
XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(XmlWriter.Create(ms));  
serializer.WriteObject(writer, new Customer(), new MyCustomerResolver());  
writer.Flush();  
ms.Position = 0;  
Console.WriteLine(((Customer)serializer.ReadObject(XmlDictionaryReader.CreateDictionaryReader(XmlReader.Create(ms)), false, new MyCustomerResolver()));  

Sie können ihn jedoch auch unter DataContractSerializerOperationBehavior festlegen, wie im folgenden Beispiel gezeigt.

ServiceHost host = new ServiceHost(typeof(MyService));  
  
ContractDescription cd = host.Description.Endpoints[0].Contract;  
OperationDescription myOperationDescription = cd.Operations.Find("Echo");  
  
DataContractSerializerOperationBehavior serializerBehavior = myOperationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>();  
if (serializerBehavior == null)  
{  
    serializerBehavior = new DataContractSerializerOperationBehavior(myOperationDescription);  
    myOperationDescription.Behaviors.Add(serializerBehavior);  
}  
  
SerializerBehavior.DataContractResolver = new MyCustomerResolver();  

Sie können einen Datenvertragsresolver deklarativ angeben, indem Sie ein Attribut implementieren, das auf einen Dienst angewendet werden kann. Weitere Informationen finden Sie im KnownAssemblyAttribute-Beispiel . In diesem Beispiel wird ein Attribut mit dem Namen "KnownAssembly" implementiert, das dem Verhalten des Diensts einen benutzerdefinierten Datenvertragsresolver hinzufügt.

Siehe auch