Freigeben über


Verwenden eines Datenvertragsauflösers

Mit einem Datenvertragslöser 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 "Datenvertrag bekannte Typen". Bekannte Typen werden normalerweise statisch angegeben. Das bedeutet, dass Sie beim Implementieren eines Vorgangs alle möglichen Typen kennen müssen, die der Vorgang erhalten kann. Es gibt Szenarien, in denen dies nicht zutrifft und dass bekannte Typen dynamisch angegeben werden können, ist wichtig.

Erstellen eines Datenvertragsresolvers

Das Erstellen eines Datenvertragslöser umfasst die Implementierung von zwei Methoden TryResolveType und ResolveName. Diese beiden Methoden implementieren Rückrufe, die während der Serialisierung bzw. Deserialisierung verwendet werden. Die TryResolveType Methode wird während der Serialisierung aufgerufen und nimmt einen Datentyp entgegen und ordnet ihn einem xsi:type Namen und 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 Typlöser in Ihrer Implementierung zu verwenden.

Im folgenden Beispiel wird gezeigt, wie Sie einen DataContractResolver implementieren, um eine Abbildung zu einem und von einem Datenvertragstyp namens Customer durchzuführen, der von einem Datenvertragstyp Person abgeleitet ist.

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 ein DataContractResolver Objekt definiert haben, können Sie es verwenden, indem Sie ihn an den DataContractSerializer Konstruktor übergeben, wie im folgenden Beispiel gezeigt.

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

Sie können ein DataContractResolver in einem Aufruf der DataContractSerializer.ReadObject- oder DataContractSerializer.WriteObject-Methoden 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()));  

Alternativ können Sie es auf DataContractSerializerOperationBehavior festlegen, wie im folgenden Beispiel gezeigt wird.

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 Datenvertragslöser 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 namens "KnownAssembly" implementiert, das dem Verhalten des Diensts einen benutzerdefinierten Datenvertragslöser hinzufügt.

Siehe auch