При разработке многоуровневых приложений с использование WCF + OData сервисов зачастую возникает
необходимость расширить сущностные классы на клиенте, т.е. добавить свойство,
которого нет в серверной EDMX модели.
Например вот так:
public partial class Enterprise : global::System.ComponentModel.INotifyPropertyChanged
{
public string NewProperty
{
get
{
…
}
}
}
}
Однако, добавив новое свойство, мы получаем ошибку времени
выполнения связанную с невозможностью сериализации вновь добавленного члена
класса. Дело в том, что при сериализации и отправке запроса на сервер
выполняется сверка XML описания объектов, соответственно, т.к. свойство добавлено
только на клиенте генерируется исключение. Решение проблемы - пометить свойство
как не подлежащее сериализации. Для этого потребуется создать атрибут, которым будем
помечать свойства, расширяющие клиентскую модель и необходимо реализовать метод
который должен быть подписан на событие сериализации сущности (DataServiceContext.WritingEntity). Задачей метода
является удаление свойств, помеченных атрибутом запрета сериализации, из XML схемы описания объекта. Синтаксис
метода ниже:
void
DataServiceContextEx_WritingEntity
(object sender, ReadingWritingEntityEventArgs e)
{
// e.Data - сериализуемый элемент
xnEntityProperties = XName.Get("properties"
,e.Data.GetNamespaceOfPrefix("m").NamespaceName);
XElement xePayload = null;
foreach (PropertyInfo property in e.Entity.GetType().GetProperties())
{
object[] doNotSerializeAttributes =
property.GetCustomAttributes(typeof(DoNotSerializeAttribute), false);
if (doNotSerializeAttributes.Length
> 0)
{
if (xePayload == null)
{
xePayload =
e.Data
.Descendants()
.Where<XElement>(xe => xe.Name == xnEntityProperties)
.First<XElement>();
}
XName xnProperty = XName.Get(property.Name,
e.Data.GetNamespaceOfPrefix("d").NamespaceName);
foreach (XElement xeRemoveThisProperty in
xePayload.Descendants(xnProperty).ToList())
{
xeRemoveThisProperty.Remove();
}
}
}
}
Ну
а
синтаксис
атрибута
совсем
простой:
[AttributeUsage(AttributeTargets.Property)]
[AttributeUsage(AttributeTargets.Property)]
public class DoNotSerializeAttribute : Attribute
{
}
Вот и всё!