Я хочу, чтобы мой сервис мог принимать и возвращать типы, полученные из BaseType
, не зная, какими будут эти типы. Я почти получил решение, используя пользовательский DataContractResolver
на основе SharedTypeResolver from this excellent blog post.Deserialize производные типы в службе WCF как базовые типы, но сохранить информацию о типе
Недостающий фрагмент головоломки заключается в том, что типы, которые будет обрабатывать мои службы, могут не использоваться совместно и не известны службе, но я все же хочу их принять и знать, какой тип должен был быть. Я привел следующий пример службы, которая действует как стек. Вы можете нажать и поместить любой тип, полученный от BaseType
при условии, что вы используете SharedTypeResolver
, и типы разделяются между клиентом и сервером.
[DataContract]
public class BaseType
{
[DataMember]
public string SomeText { get; set; }
public override string ToString()
{
return this.GetType().Name + ": " + this.SomeText;
}
}
[DataContract]
public class DerivedType : BaseType
{
[DataMember]
public int SomeNumber { get; set; }
public override string ToString()
{
return base.ToString() + ", " + this.SomeNumber;
}
}
[ServiceContract]
public interface ITypeStack
{
[OperationContract]
void Push(BaseType item);
[OperationContract]
BaseType Pop();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class TypeStackService : ITypeStack
{
private Stack<BaseType> stack = new Stack<BaseType>();
public void Push(BaseType item)
{
this.stack.Push(item);
}
public BaseType Pop()
{
return this.stack.Pop();
}
}
Это, очевидно, очень упрощенный пример проблемы, с которой я сталкиваюсь. Клиент может довольно весело нажать и поп BaseType
или DerivedType
, потому что оба клиента и сервер знают о них, но если клиент толкает UnsharedType
, который служба не знает, я получаю сообщение об ошибке, как и следовало ожидать.
Форматировщик бросил исключение при попытке десериализации сообщения: Была ошибку при попытке десериализации параметра http://tempuri.org/:item. Сообщение InnerException было «Ошибка в строка 1 позиция 316. Элемент« http://tempuri.org/:item »содержит данные от типа, который сопоставляется с именем« TestWcfClient, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null: TestWcfClient.UnsharedType ' , Deserializer не знает ни одного типа, который соответствует этому названию. Рассмотрим изменение реализации метода ResolveName на вашем DataContractResolver вернуть ненулевое значение для имени «TestWcfClient.UnsharedType» и пространства имен «TestWcfClient, Version = 1.0.0.0, культура = нейтральной, PublicKeyToken = NULL» «. , Пожалуйста, см. InnerException для получения более подробной информации.
Мое текущее мышление, чтобы добавить IExtensibleDataObject
в BaseType
для хранения значений от неразделенного типа и сделать неразделенный тип выглядеть BaseType
к службе на десериализации, когда элемент выталкивается; противоположное должно произойти, когда элемент выскочит. Я просто не знаю, как это сделать. Мои мысли до сих пор о возможных подходах:
- Дополнительная настройка для
DataContractResolver
, которые могут включать в себяTypeDelegator
- Использование
IDataContractSurrogate
вместо неподеленной типа - Каким-то образом сохранить сериализированную XML сервис получил, когда элемент выталкивается , а затем использовать это в ответе, когда элемент выталкивается
- Использование сообщения инспектора манипулировать сообщениями
Я понятия не имею, будет ли кто-нибудь из них работать, что будет задействовано или что будет лучшим решением. Вы?
Вы будете менять объекты на службе, или вам просто нужно их хранить и отправить обратно клиентам? – Enes
Просто храните и отправляйте обратно. Мне нужно знать о базовом типе, поскольку у него есть некоторые свойства, которые служба использует для влияния на хранилище, но он доступен только для чтения, насколько это касается службы. – batwad