Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Un sistema di risoluzione del contratto dati consente di configurare i tipi noti in modo dinamico. I tipi noti sono necessari durante la serializzazione o la deserializzazione di un tipo non previsto da un contratto dati. Per altre informazioni sui tipi noti, vedere Tipi noti del contratto dati. I tipi noti vengono normalmente specificati in modo statico. Ciò significa che è necessario conoscere tutti i tipi possibili che un'operazione può ricevere durante l'implementazione dell'operazione. Esistono scenari in cui questo non è vero e la possibilità di specificare tipi noti in modo dinamico è importante.
Creazione di un risolutore per contratti di dati
La creazione di un sistema di risoluzione del contratto dati prevede l'implementazione di due metodi, TryResolveType e ResolveName. Questi due metodi implementano i callback usati rispettivamente durante la serializzazione e la deserializzazione. Il TryResolveType metodo viene richiamato durante la serializzazione e accetta un tipo di contratto di dati e lo mappa a un xsi:type nome e uno spazio dei nomi. Il metodo ResolveName viene richiamato durante la deserializzazione e accetta un xsi:type nome e un namespace, risolvendoli in un tipo di contratto dati. Entrambi questi metodi hanno un knownTypeResolver parametro che può essere usato per usare il sistema di risoluzione dei tipi noti predefinito nell'implementazione.
Nell'esempio seguente viene illustrato come implementare un DataContractResolver per mappare verso e da un tipo di contratto dati denominato Customer derivato da un tipo di contratto dati Person.
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);
}
}
}
Dopo aver definito un oggetto DataContractResolver , è possibile usarlo passandolo al DataContractSerializer costruttore, come illustrato nell'esempio seguente.
XmlObjectSerializer serializer = new DataContractSerializer(typeof(Customer), null, Int32.MaxValue, false, false, null, new MyCustomerResolver());
È possibile specificare un oggetto DataContractResolver in una chiamata ai DataContractSerializer.ReadObject metodi o DataContractSerializer.WriteObject , come illustrato nell'esempio seguente.
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()));
In alternativa, è possibile impostarlo su DataContractSerializerOperationBehavior come illustrato nell'esempio seguente.
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();
È possibile specificare in modo dichiarativo un resolver del contratto dati implementando un attributo che può essere applicato a un servizio. Per altre informazioni, vedere l'esempio KnownAssemblyAttribute . Questo esempio implementa un attributo denominato "KnownAssembly" che aggiunge un resolver di contratto dati personalizzato al comportamento del servizio.