Usando um resolvedor de contrato de dados

Um resolvedor de contrato de dados permite configurar tipos conhecidos dinamicamente. Os tipos conhecidos são necessários ao serializar ou desserializar um tipo não esperado por um contrato de dados. Para obter mais informações sobre tipos conhecidos, consulte Tipos conhecidos de contrato de dados. Os tipos conhecidos são normalmente especificados estaticamente. Isso significa que você teria que conhecer todos os tipos possíveis que uma operação pode receber durante a implementação da operação. Há cenários em que isso não é verdade e ser capaz de especificar tipos conhecidos dinamicamente é importante.

Criando um resolvedor de contrato de dados

A criação de um resolvedor de contrato de dados envolve a implementação de dois métodos, TryResolveType e ResolveName. Esses dois métodos implementam retornos de chamada que são usados durante a serialização e desserialização, respectivamente. O TryResolveType método é invocado durante a serialização e usa um tipo de contrato de dados e o mapeia para um xsi:type nome e namespace. O ResolveName método é invocado durante a desserialização e usa um xsi:type nome e um namespace e o resolve para um tipo de contrato de dados. Ambos os métodos têm um knownTypeResolver parâmetro que pode ser usado para usar o resolvedor de tipo conhecido padrão em sua implementação.

O exemplo a seguir mostra como implementar um DataContractResolver para mapear de e para um tipo de contrato de dados chamado Customer derivado de um tipo Personde contrato de dados .

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

Depois de definir um DataContractResolver , você pode usá-lo passando-o para o construtor, DataContractSerializer conforme mostrado no exemplo a seguir.

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

Você pode especificar um DataContractResolver em uma chamada para os DataContractSerializer.ReadObject métodos ou DataContractSerializer.WriteObject , conforme mostrado no exemplo a seguir.

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

Ou você pode defini-lo no DataContractSerializerOperationBehavior como mostrado no exemplo a seguir.

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

Você pode especificar declarativamente um resolvedor de contrato de dados implementando um atributo que pode ser aplicado a um serviço. Para obter mais informações, consulte o exemplo KnownAssemblyAttribute . Este exemplo implementa um atributo chamado "KnownAssembly" que adiciona um resolvedor de contrato de dados personalizado ao comportamento do serviço.

Consulte também