Как инициализировать абстрактный базовый конструктор, когда клиент вызывает new на DataContract?
Я пытаюсь найти обходной путь, который бы позволял инициализировать конструктор абстрактного базового класса, когда клиент, использующий мой сервис WCF, выполняет new()
над объектом DataContract. Мне известно, что объекты DataContract создаются как необработанные, неинициализированные объекты, поэтому конструкторы не вызываются. Я столкнулся с пользователем [OnSerializing]
, [OnSerialized]
, [OnDeserializing]
, а также [OnDeserialized]
атрибуты, и я обнаружил, что они не учитываются механизмом сериализации WCF, если вы явно не заставите его использовать XML, что нежелательно в данном конкретном случае. Вот очень упрощенный пример кодирования того, что я пытаюсь использовать.
[DataContract(Namespace = "http://somenamespace/Data/ContractBase/v1")]
public abstract ContractBase
{
[DataMember(IsRequired = true)]
public SomeDataContract BaseClassObject { get; set; }
public string Name { get; set; }
public ContractBase()
{
BaseClassObject = new SomeDataContract("randomConstructorArgument");
Name = "Ezra";
}
}
[DataContract(Namespace = "http://somenamespace/Data/TheClass/v1")]
[KnownType(typeof(ContractBase))]
public sealed class TheClass : ContractBase
{
[DataMember]
public PetDataContract MyPet { get; set; }
[DataMember]
public int SomeIntProperty { get; set; }
public TheClass()
: base()
{
MyPet = new PetDataContract ("Fido");
SomeIntProperty = -1;
}
}
Я знаю, что клиент выполняет TheClass myClass = new TheClass();
не будет инициализировать базовый конструктор, так как конструктор TheClass
никогда не называется. Я попытался добавить такие методы, как следующие, чтобы инициировать, когда сериализация происходит без какого-либо успеха.
private void Initialize()
{
MyPet = new PetDataContract ("Fido");
SomeIntProperty = -1;
base.Initialize();
}
[OnSerializing]
private void OnSerializing(StreamingContext c)
{
Initialize();
}
Базовый класс также будет иметь метод Initialize, чтобы "конструкторы" были связаны. Сами конструкторы будут обновлены, чтобы включить Initialize();
позвоните, чтобы использовать тот же общий источник кода.
Есть ли способ справиться с этим без принудительного выполнения сериализации через XmlSerializer
? Мой текущий обходной путь - предоставить метод в службе WCF для создания объекта на сервере и возврата версии после конструктора.
public TheClass CreateTheClass(TheClass contract)
{
// Calls the constructor of TheClass and its base constructor.
return new TheClass();
}
Это работает, как и ожидалось, но это дополнительный сервисный вызов, которого я бы предпочел избежать из-за стоимости сетевого ввода-вывода. Любая помощь будет чрезвычайно ценится.
Спасибо!
1 ответ
Согласно этой статье, атрибуты, которые вы упомянули, должны хорошо работать DataContractSerializer
, Ваш последний пример немного странный - вы пытаетесь использовать OnSerializing
атрибут, говоря, что конструкторы не вызываются во время десериализации WCF.
Я бы предложил использовать ваш подход с Initialize
методы отмечены OnDeserializing
(или же OnDeserialized
если вы хотите вызвать свой код после завершения десериализации) атрибут.