我们有一个仅在.NET 4.5中发生的序列化问题 - 相同的代码在.NET 4中运行良好。我们尝试使用几个字段序列化一个继承的类型,基类和继承类都标有 SerializableAttribute 即可。我们在Web服务的客户端获得一个例外,说服务器中有 MethodAccessException ,服务器本身不会抛出任何异常,这似乎是客户端序列化过程中的一个问题。 值得注意的是,我们正在使用.NET 4-而不是.4.5进行编译
更新:实施 ISerailize 并忽略“Value”属性后,程序运行正常,但这意味着我们不得不放弃序列化此字段。
任何帮助都将非常感激。谢谢, 奥马尔
例外情况:
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:
附件是基类和继承类代码: 的 基 :
[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
}
答案 0 :(得分:16)
在4.5中,XmlSerializer的实现被替换为不依赖于C#编译器的实现。虽然它提供了更好的启动性能和稳定性,但您可能会遇到实现之间的兼容性问题。您是否可以尝试将以下内容添加到app.config文件中,看看是否可以解决问题?
<configuration>
<system.xml.serialization>
<xmlSerializer useLegacySerializerGeneration="true"/>
</system.xml.serialization>
</configuration>
如果您担心在4.0上运行此工作,您可以尝试在运行时检测框架的版本,并在运行时为4.5或更高时动态更改配置。我写了一篇博客文章,后来解释了如何做到这一点:
答案 1 :(得分:5)
我们希望在即将推出的.NET Framework 4.5更新中解决此问题。我会在更新发布后立即使用下载链接更新帖子。如果您的任务关键型应用程序受到影响,请联系Microsoft dot com的netfx45compat,并急需修复。我可以帮助您找到可以帮助您的Microsoft支持。
答案 2 :(得分:2)
我也有这样的序列化失败。在我的情况下,它是由[DefaultValue(..)]
属性的类型不匹配引起的。对于"1.0d"
类型的属性,我有一个附加的默认值decimal
(双精度)。似乎XmlSerializer的新实现不能再转换这些值,但旧的可以。还可以通过在“App.config”中添加属性来切换回旧版本的XmlSerializer。但微软(和我)不推荐这样做。希望这有助于某人。
答案 3 :(得分:1)
我更仔细地研究了你的类型,问题可能是由于:
之间的冲突造成的public virtual object @Value
{
}
基地上的和:
private new object Value
{
}
答案 4 :(得分:0)
我最近遇到了同样的问题,并找到了实际原因和正确的解决方案。
此问题是由XML序列化程序测试属性/字段的默认值引起的。如果该字段值与DefaultValue属性匹配,它将不会序列化以节省空间。 “十进制”类型的DefaultValue没有重载,因此十进制值将转换为浮点数,这是重载之一。
您必须明确地告诉属性它是一个小数:
[DevaultValue(typeof(decimal), "1.56")]
请注意,在字段上使用DefaultValue不会在反序列化时将该字段设置为该值。您仍然必须在构造函数中或作为字段初始值设定项来设置正确的值:
[DefaultValue(typeof(decimal), "1.56")]
decimal MyValue { get; set; } = 1.56;