Использование арбитра контрактов данных
Арбитр контрактов данных позволяет динамически настраивать известные типы. Известные типы необходимы для сериализации или десериализации типов, не предусмотренных контрактом данных. Дополнительные сведения о известных типах см. в разделе "Известные типы контракта данных". Известные типы обычно задаются статически. Это означает, что при реализации операции необходимо знать все типы, которые могут быть переданы операции. Существуют сценарии, в которых это не так, и важно иметь возможность динамического задания типов.
Создание арбитра контрактов данных
Создание арбитра контрактов данных включает реализацию двух методов: TryResolveType и ResolveName. Эти методы реализуют обратные вызовы, используемые при сериализации и десериализации соответственно. Метод TryResolveType вызывается при сериализации, принимает тип контракта данных и сопоставляет его с именем xsi:type
и пространством имен. Метод ResolveName вызывается при десериализации, принимает имя xsi:type
и пространство имен и сопоставляется с типом контракта данных. Оба метода содержат параметр knownTypeResolver
, который позволяет использовать в реализации арбитр известного типа по умолчанию.
В следующем примере показана реализация DataContractResolver для сопоставления с типом контракта данных с именем Customer
, производного от типа контракта данных 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);
}
}
}
После определения DataContractResolver его можно передать в конструктор DataContractSerializer, как показано в следующем примере.
XmlObjectSerializer serializer = new DataContractSerializer(typeof(Customer), null, Int32.MaxValue, false, false, null, new MyCustomerResolver());
Можно указать DataContractResolver в вызове метода DataContractSerializer.ReadObject или DataContractSerializer.WriteObject, как показано в следующем примере.
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()));
Или же можно задать его для DataContractSerializerOperationBehavior, как показано в следующем примере.
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();
Сопоставитель контрактов данных можно задать декларативно, реализовав атрибут, применяемый к службе. Дополнительные сведения см. в примере KnownAssemblyAttribute . В этом примере реализован атрибут с именем "KnownAssembly", который добавляет в поведение службы настраиваемый сопоставитель контракта данных.