c# - 如果调用的类包含 [OnDeserialized] 方法,则在 .NET 应用程序中使用 PCL 时出现 TypeLoadException

标签 c# serialization attributes forward-declaration portable-class-library

我正在将现有的 .NET 类库改编为可移植类库。我正在使用配置文件 78(.NET 4.5、Windows Store 8、Windows Phone 8)而不是配置文件 158(它也针对 Silverlight 5),因为我希望能够编译 unsafe 代码原始库。

.NET 库包含很多标记为 [Serializable] 的类,因此我实现了一个包含虚拟 SerializableAttribute 实现的支持 PCL 库:

public class SerializableAttribute : Attribute { }

这是从主 PCL 库中引用的。

为了在 .NET 应用程序中充分使用主 PCL 库,同时避免类型名称冲突,我还准备了一个 .NET 支持库(与 PCL 支持库具有相同的 strong 名称),其中包含类型转发声明:

[assembly: TypeForwardedTo(SerializableAttribute)]

并且在我的 .NET 应用程序中明确引用 .NET 支持库而不是 PCL 库。

在准备好所有这些并能够成功编译 PCL 适配库后,我重新使用原始 .NET 库中的单元测试,现在引用 PCL 主库和 < em>.NET 支持库。

这通常工作得很好,但对于包含 [Serializable] 类和 [OnDeserialized] 装饰方法的单元测试:

[Serializable]
public class Foo
{
    [OnDeserialized]
    private void DoSomething(StreamingContext context) { }
}

我得到以下 TypeLoadException:

Type 'Foo' in assembly 'MyPclAssembly' has method 'DoSomething' with an incorrect signature for the serialization attribute that it is decorated with.

(可以注意到 OnDeserializedAttribute 包含在可移植子集中,大概是因为它也在 [DataContract] 序列化中被识别。 )

在原始 .NET 库上运行单元测试时,我没有获得异常。我仔分割析了 Foo 类中的方法签名,它完全符合这些(反)序列化辅助方法应该具有的签名,参见例如here .我还尝试将 [OnDeserialized] 方法的可见性更改为 internalpublic,但无济于事。

使用PCL库时出现这个异常的原因是什么,如何避免?


编辑 我检查了 PCL 库的 IL 代码和 .NET 库的 [OnDeserialized] 方法,我看不出任何相关的区别:

PCL

.method private hidebysig instance void DoSomething(valuetype [System.Runtime.Serialization.Primitives]System.Runtime.Serialization.StreamingContext context) cil managed

.NET

.method private hidebysig instance void  DoSomething(valuetype [mscorlib]System.Runtime.Serialization.StreamingContext context) cil managed

StreamingContext 的程序集引用不同,但我假设 PCL System.Runtime.Serialization.Primitives 程序集只是一个到 mscorlib 的类型转发程序集 类型?

现在,我决定从我的 PCL 项目中排除 [OnDeserialized] 方法,因为我无论如何都不打算使用序列化。不过,仍然欢迎回答我为什么遇到 TypeLoadException

最佳答案

是的,这是一场你赢不了的游戏。在前面,[Serializable] 属性只与 BinaryFormatter 类相关,该类实现二进制序列化。该类在驻留在手机或平板电脑上的 .NET Framework 版本中可用,因此没有必要尝试让它工作。

您正在与 .NET 中的类型标识 概念作斗争。其中指出类型不仅由命名空间和类型名称标识,而且还由它来自的程序集标识。这是一种非常强大的反 DLL hell 对策,您在这里通过使用在目标体系结构上不可用的类型来避开这种对策。

冷酷的事实是,在 4.5 PCL 库中,StreamingContext 类型存在于 System.Runtime.Serialization.dll 程序集中。针对桌面的应用程序将使用来自 mscorlib.dll 的应用程序。它不是转发类型,它是重复的。 System.Runtime.Serialization.dll 程序集是一个小型填充程序集,其明确目的是隔离这些依赖项并防止 DLL Hell。

Kaboom 在运行时,它发现一个方法的参数类型标识错误。

关于c# - 如果调用的类包含 [OnDeserialized] 方法,则在 .NET 应用程序中使用 PCL 时出现 TypeLoadException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20666731/

相关文章:

c# - 如何在 List<String> 中搜索任何文本

python - Django rest framework : serializers. ReadOnlyField() 不在可浏览的 api 中显示字段

java - 将消息对象从 JavaMail 保存到文件系统

html - 脚本和样式元素的 HTML "nonce"属性的用途是什么?

PHP 在现有 XML 文件上添加子项和属性

c# - 为什么主机玩家没有权限发送服务器【命令】?统一-镜子

c# - 为什么每个人都说 SpinLock 更快?

Django:如何将自定义字段序列化为 fixture 并将其加载回来

javascript - jquery attr 选择器不选择属性的整个值

c# - Azure B2C 身份提供商登录失败 : AADB2C99002: User does not exist