Мне нужно иметь 2 семейства классов (одно на сервере и одно на стороне клиента), которые идентичны по структуре данных, но отличаются по поведению.Также я предполагаю, что эти почтовые сообщения будут достаточно большими, поэтому я не хочу реализовывать промежуточный уровень DTO и преобразований в него и из него.Я решил двигаться следующим образом: объявить совместно используемую сборку с объявлением интерфейсов данных и сервисов, подобных этим:
public interface ITest
{
string Title { get; set; }
int Value { get; set; }
}
public interface IService
{
ITest GetData();
}
Имея эти объявления, я могу реализовать эти интерфейсы на стороне сервера, например, на основе Entity Framework (data) и WCF (услуги).На стороне клиента я могу использовать, например, Dependency Properties (данные) и WCF (сервис).Когда я начал пытаться реализовать это, я встретил несколько проблем.Сначала речь шла о серверной стороне WCF - он просто не хочет работать с интерфейсами в качестве возвращаемых параметров.Благодаря StackOverflow эта проблема была решена следующим образом: здесь .
Следующая проблема заключается в том, что XML, отображаемый на стороне сервера, содержит уточненное имя сборки, сериализованное в классе сервера.
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetDataResponse xmlns="http://tempuri.org/">
<Test z:Id="1" z:Type="Dist.Server.Model.Test" z:Assembly="Dist.Server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" xmlns="http://schemas.datacontract.org/2004/07/Dist.Server.Model" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<Title z:Id="2">Test</Title>
<Value>123</Value>
</Test>
</GetDataResponse>
</s:Body>
</s:Envelope>
Таким образом, при десериализации на стороне клиента была попытка загрузить этот тип.Поскольку этот тип недоступен на стороне клиента, мне пришлось реализовать какое-то отображение типов.Я обнаружил, что это довольно просто, поскольку NetDataContractSerializer , используемый для сериализации, поддерживает свойство Binder .Таким образом, я переопределяю это свойство на стороне клиента и возвращаю правильное значение (в то же время жесткий код, но это нормально для тестов).
public class NetBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName) {
var type = Type.GetType("Client.Test, Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
return type;
}
}
Теперь у меня есть следующая картина:
- Сервер использует NetDataContractSerializer для сериализации ответа.Он использует фактическое значение (calss) во время сериализации вместо типа, используемого в объявлении сервиса (интерфейса).
- Клиентская сторона получает XML и запускает десериализацию.Чтобы разрешить тип, NetDataContractSerializer вызывает мой Binder, который возвращает правильный тип.
- NetDataContractSerializer создает экземпляр правильного типа и начинает загрузку его свойств.
И вот я получилБеда, которую я не знаю, как решить.Значения свойств не десериализованы.Это означает, что экземпляр класса создан правильно (неинициализированный экземпляр создан с помощью служб отражения), но все свойства имеют значения по умолчанию (0 или ноль).Я попытался поиграть с объявлением класса на стороне клиента: пометить его как [Serializable], реализовать ISerializable и т. Д., Но ничто не помогает. NetDataContractSerializer требует, чтобы класс был помечен как [DataContract] или [Serializable].Первый параметр оставляет свойства пустыми, второй вызывает исключения, такие как « является неожиданным, ожидаемым является bla-bla-bla_Value_Ending_bla-bla-bla».
У кого-нибудь есть какие-либо предложения по решению этого последнего шага?
Я могу предоставить полные источники для лучшего понимания, но я не знаю, могу ли я прикрепить их здесь ...
Заранее спасибо.