Udostępnij za pośrednictwem


Używanie mechanizmu rozpoznawania kontraktów danych

Narzędzie do rozpoznawania kontraktów danych umożliwia dynamiczne konfigurowanie znanych typów. Znane typy są wymagane w przypadku serializacji lub deserializacji typu, który nie jest oczekiwany przez kontrakt danych. Aby uzyskać więcej informacji na temat znanych typów, zobacz Znane typy kontraktów danych. Znane typy są zwykle określane statycznie. Oznacza to, że należy znać wszystkie możliwe typy, które może otrzymać operacja podczas implementowania operacji. Istnieją scenariusze, w których nie jest to prawdą i możliwość dynamicznego określania znanych typów jest ważna.

Tworzenie narzędzia do rozpoznawania kontraktów danych

Tworzenie narzędzia rozpoznawania kontraktów danych obejmuje zaimplementowanie dwóch metod i TryResolveTypeResolveName. Te dwie metody implementują wywołania zwrotne, które są używane odpowiednio podczas serializacji i deserializacji. Metoda TryResolveType jest wywoływana podczas serializacji i przyjmuje typ kontraktu danych i mapuje ją na xsi:type nazwę i przestrzeń nazw. Metoda ResolveName jest wywoływana podczas deserializacji i przyjmuje xsi:type nazwę i przestrzeń nazw i rozpoznaje ją jako typ kontraktu danych. Obie te metody mają knownTypeResolver parametr, który może służyć do używania domyślnego znanego rozpoznawania typów w implementacji.

W poniższym przykładzie pokazano, jak zaimplementować element DataContractResolver do mapowania na i z typu kontraktu danych o nazwie Customer pochodzącego z typu Personkontraktu danych .

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);  
        }  
    }  
}  

Po zdefiniowaniu DataContractResolver elementu można go użyć, przekazując go do konstruktora DataContractSerializer , jak pokazano w poniższym przykładzie.

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

Można określić DataContractResolver w wywołaniu metody DataContractSerializer.ReadObject lub DataContractSerializer.WriteObject , jak pokazano w poniższym przykładzie.

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()));  

Możesz też ustawić go na obiekcie DataContractSerializerOperationBehavior , jak pokazano w poniższym przykładzie.

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();  

Można deklaratywnie określić rozpoznawanie kontraktu danych, implementując atrybut, który można zastosować do usługi. Aby uzyskać więcej informacji, zobacz przykład KnownAssemblyAttribute . Ten przykład implementuje atrybut o nazwie "KnownAssembly", który dodaje niestandardowy moduł rozpoznawania kontraktów danych do zachowania usługi.

Zobacz też