Сериализация прерываний в .NET 4.5
У нас есть проблема с сериализацией, которая возникает только в .NET 4.5 - тот же код отлично работает в .NET 4. мы пытаемся сериализовать унаследованный тип с несколькими полями, как базовый, так и унаследованный класс помечены SerializableAttribute. Мы получаем исключение на клиентской стороне веб-службы, говоря, что на сервере было MethodAccessException, сам сервер не выбрасывает никаких исключений, похоже, это проблема в процессе сериализации клиента.
Важно отметить, что мы компилируем в .NET 4- not.4.5
Обновление. После реализации ISerailize и игнорирования свойства "Значение" программа выполнялась правильно, но это означает, что нам пришлось отказаться от сериализации этого поля.
любая помощь будет наиболее оценена. Благодаря,
Омер
Сведения об исключении:
System.Web.Services.Protocols.SoapException occurred
HResult=-2146233087
Message=System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.InvalidOperationException: There was an error generating the XML document. ---> System.MethodAccessException: Attempt by method 'Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write88_DeviceSiteTypeInfo(System.String, System.String, IOSIGHT.Info.DeviceSiteTypeInfo, Boolean, Boolean)' to access method 'IOSIGHT.Info.DeviceSiteTypeInfo.get_Value()' failed.
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write88_DeviceSiteTypeInfo(String n, String ns, DeviceSiteTypeInfo o, Boolean isNullable, Boolean needType)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write1310_GetSiteTypesResponse(Object[] p)
at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer2089.Serialize(Object objectToSerialize, XmlSerializationWriter writer)
at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
at System.Web.Services.Protocols.SoapServerProtocol.WriteReturns(Object[] returnValues, Stream outputStream)
at System.Web.Services.Protocols.WebServiceHandler.WriteReturns(Object[] returnValues)
at System.Web.Services.Protocols.WebServiceHandler.Invoke()
--- End of inner exception stack trace ---
Source=System.Web.Services
Actor=""
Lang=""
Node=""
Role=""
StackTrace:
at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at IOSIGHT.BLL.localhost.IOSightWS.GetSiteTypes() in C:\IOSIGHT\Common\IOSight.BLL\Web References\localhost\Reference.cs:line 25019
at IOSIGHT.BLL.TypeBankBLL.GetSiteTypes() in C:\IOSIGHT\Common\IOSight.BLL\Entities\TypeBanksBLL.cs:line 477
InnerException:
Прикрепленный код базового и унаследованного классов:
Base
[Serializable()]
public class TypeBankInfo
{
#region "Fields"
private int _id = 0;
private string _Name = string.Empty;
private string _description = string.Empty;
private object _value = null;
#endregion
#region "Constructors"
public TypeBankInfo()
{
}
public TypeBankInfo(int ID, string name)
: this()
{
this._id = ID;
this.Name = name;
}
public TypeBankInfo(int ID, string name, string description)
: this(ID, name)
{
this._description = description;
this._value = Value;
}
public TypeBankInfo(int ID, string name, string description, object value)
: this(ID, name, description)
{
this._value = value;
}
#endregion
#region "Properties"
public virtual string Name
{
get
{
return this._Name;
}
set
{
this._Name = value;
}
}
public virtual string Description
{
get
{
return _description;
}
set
{
_description = value;
}
}
public virtual int ID
{
get
{
return _id;
}
set
{
_id = int.Parse(value.ToString());
}
}
public virtual object @Value
{
get
{
return this._value;
}
set
{
this._value = value;
}
}
#endregion
}
Intheried
[Serializable()]
public class DeviceSiteTypeInfo : TypeBankInfo, ISerializable
{
#region "Fields"
private EntityTypeEnum _entitytype = EntityTypeEnum.Site;
private DeviceIOTemplateInfo[] _IOTemplates;
private CaptionInfo[] _Captions;
private int _parentClassID;
#endregion
#region "Constructors"
public DeviceSiteTypeInfo()
{
}
public DeviceSiteTypeInfo(int id, string name)
: base(id, name)
{
}
public DeviceSiteTypeInfo(int id, string name, string description)
: base(id, name, description)
{
}
// The special constructor is used to deserialize values.
public DeviceSiteTypeInfo(SerializationInfo info, StreamingContext context)
{
//parent fields
ID = (int)info.GetValue("_id", typeof(int));
Name = (string)info.GetValue("_Name", typeof(string));
Description = (string)info.GetValue("_description", typeof(string));
//my fields
_entitytype = (EntityTypeEnum)info.GetValue("_entitytype", typeof(EntityTypeEnum));
_IOTemplates = (DeviceIOTemplateInfo[])info.GetValue("_IOTemplates", typeof(DeviceIOTemplateInfo[]));
_Captions = (CaptionInfo[])info.GetValue("_Captions", typeof(CaptionInfo[]));
_parentClassID = (int)info.GetValue("_parentClassID", typeof(int));
}
#endregion
#region "Properties"
public EntityTypeEnum EntityTypeID
{
get
{
return this._entitytype;
}
set
{
this._entitytype = value;
}
}
[EditorBrowsable(EditorBrowsableState.Never), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
private new object Value
{
get
{
return base.Value;
}
set
{
base.Value = value;
}
}
public CaptionInfo[] Captions
{
get
{
return this._Captions;
}
set
{
this._Captions = value;
}
}
public DeviceIOTemplateInfo[] IOTemplates
{
get
{
return this._IOTemplates;
}
set
{
this._IOTemplates = value;
}
}
public int ParentClassID
{
get
{
return this._parentClassID;
}
set
{
this._parentClassID = value;
}
}
#endregion
#region Methods
/// <summary>
/// Called on serialization
/// </summary>
/// <param name="info">serialiation info</param>
/// <param name="context">context</param>
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
// parent fields
info.AddValue("_id", ID, typeof(int));
info.AddValue("_Name", Name, typeof(string));
info.AddValue("_description", Description, typeof(string));
//my fields
info.AddValue("_entitytype", _entitytype, typeof(EntityTypeEnum));
info.AddValue("_IOTemplates", _IOTemplates, typeof(DeviceIOTemplateInfo[]));
info.AddValue("_Captions", _Captions, typeof(CaptionInfo[]));
info.AddValue("_parentClassID", _parentClassID, typeof(int));
}
#endregion
}
Ответы
Ответ 1
В 4.5, реализация XmlSerializer была заменена на ту, которая не зависит от компилятора С#. Хотя он обеспечивает лучшую производительность и стабильность при запуске, вы можете столкнуться с проблемой совместимости между реализациями. Можете ли вы попробовать добавить следующее в файл app.config и посмотреть, устраняет ли это проблему?
<configuration>
<system.xml.serialization>
<xmlSerializer useLegacySerializerGeneration="true"/>
</system.xml.serialization>
</configuration>
Если вы обеспокоены тем, что эта работа работает в версии 4.0, вы можете попробовать обнаружить версию фреймворка во время выполнения и динамически изменить конфигурацию, если время выполнения составляет 4.5 или выше. Я написал сообщение в блоге некоторое время назад, объясняя, как это сделать:
http://blogs.msdn.com/b/youssefm/archive/2010/01/21/how-to-change-net-configuration-files-at-runtime-including-for-wcf.aspx
Ответ 2
Мы рассмотрим эту проблему в предстоящем обновлении .NET Framework 4.5. Я обновлю ссылку на скачивание, как только будет выпущено обновление. Пожалуйста, свяжитесь с netfx45compat в Microsoft dot com, если у вас есть критически важное приложение, которое повлияло, и исправление требуется срочно. Я могу помочь вам в поддержке Microsoft, которая может помочь с вашим запросом.
Ответ 3
Я посмотрел на ваши типы более близко, и проблема, скорее всего, вызвана конфликтом между:
public virtual object @Value
{
}
на базе и:
private new object Value
{
}
в классе Derived. Вот две вещи, которые я хотел бы попробовать:
- Попробуйте публиковать "новое значение объекта". Там может быть проблема доступа к членству.
- Попробуйте переименовать базу "@Value" в нечто вроде "BaseValue" или другое подходящее имя. Возможно, возникла проблема с использованием знака "@".
Ответ 4
У меня также был такой провал сериализации. В моем случае это было вызвано несоответствием типа атрибутов [DefaultValue(..)]
. У меня было прикрепленное значение по умолчанию "1.0d"
(double) для свойства типа decimal
. Похоже, что новая реализация XmlSerializer больше не может преобразовывать такие значения, но старая. Существует также возможность вернуться к старой версии XmlSerializer, добавив атрибут в "App.config", но это не рекомендуется Microsoft (и мной). Надеюсь, это поможет кому-то.