Вы получаете SerializationException
, означающее, что .NET не знает, как десериализовать часть данных, которые вы отправляете.В этом случае он захлебывается ArrayOfanyType
, который является любым видом неуниверсальной коллекции (например, ArrayList
или простой массив).
Я рассмотрел источник для IronPython 2.7.1(какую версию вы используете?), глядя на реализацию List
и PythonTuple
.Оба содержат массив Object, в значительной степени идентичный объявленному;В List есть несколько других случайных полей экземпляров.
// IronPython.Runtime.List
internal volatile object[] _data;
private const int INITIAL_SIZE = 20;
internal int _size;
// IronPython.Runtime.PythonTuple
internal readonly object[] _data;
Я не знаю, почему сериализатор недоволен классом PythonTuple
, когда он нормально работает с List
.Однако это, вероятно, указывает на то, что средство распознавания типов .NET не может разрешить какой-либо элемент сериализованного объекта.
Существует два способа решения этой проблемы, о которых я знаю.
Вы можете попытаться убедить .NET учитывать данный тип во время десериализации, используя атрибут KnownTypes
.С MSDN :
Когда данные поступают в принимающую конечную точку, среда выполнения WCF пытается десериализовать данные в экземпляр общеязыкового типа среды выполнения (CLR).Тип, который создается для десериализации, выбирается сначала проверкой входящего сообщения, чтобы определить контракт данных, которому соответствует содержимое сообщения.Затем механизм десериализации пытается найти тип CLR, который реализует контракт данных, совместимый с содержимым сообщения.Набор типов кандидатов, который механизм десериализации допускает во время этого процесса, называется набором «известных типов» десериализатора.
Вы хотите применить этот атрибут к классу, передаваемому черезпровод, и это не удобно, когда вы не контролируете класс, как здесь.Так что это, вероятно, не стартер.
Вы можете указать пользовательский DataContractResolver
для разрешения проблемных типов:
Средство сопоставления контрактов данных позволяет динамически настраивать известные типы.Известные типы требуются при сериализации или десериализации типа, не ожидаемого контрактом данных.
Вы можете сделать это, не управляя сериализуемым классом, но это требует немного больше работы. Это сообщение в блоге MSDN имеет отличную запись.
В итоге вы создадите DataContractResolver и переопределите два его метода, TryResolveType
и ResolveName
.Первый используется во время сериализации, а второй - при десериализации.Из примера MSDN с моими комментариями:
public class MyCustomerResolver : DataContractResolver
{
public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
{
if (dataContractType == typeof(Customer)) // a type I recognize
{
XmlDictionary dictionary = new XmlDictionary();
typeName = dictionary.Add("SomeCustomer");
typeNamespace = dictionary.Add("www.FPSTroller.com");
return true;
}
else // I don't know what this is; defer to the inbuilt type resolver
{
return knownTypeResolver.TryResolveType(dataContractType, declaredType, null, out typeName, out typeNamespace);
}
}
public override Type ResolveName(string typeName, string typeNamespace, DataContractResolver knownTypeResolver)
{
// my type
if (typeName == "SomeCustomer" && typeNamespace == "http://www.FPSTroller.com")
{
return typeof(Customer);
}
else // I don't know what this is; defer to the inbuilt type resolver
{
return knownTypeResolver.ResolveName(typeName, typeNamespace, null);
}
}
}
В сообщении блога, о котором я упоминал выше, есть некоторые примеры распознавателей, которые могут дать .NET лучший шанс и обрабатывать ваши классы без написания ничего особенного (ищите " Полезные распознаватели"заголовок).
Вы бы использовали DataContractSerializerOperationBehavior
.Подключить ваш резольвер в WCF;см. пример в документации MSDN .
Наконец, прежде чем идти по этому пути, вы можете подумать об изменении интерфейса операций WCF.Вам действительно нужно передавать эти нестандартные типы по проводам?То, что я прочитал, подразумевает, что неуниверсальные типы часто сталкиваются с такой проблемой.Попробуйте использовать старый System.Collections.Generic.Dictionary<K,V>
и (если вы используете .NET 4+) System.Tuple
.Зафиксируйте ваши типы;не пытайся угадать решатель.