我正在将现有的 .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]
方法的可见性更改为 internal
和 public
,但无济于事。
使用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/