c#反序列化在自动化插件中失败,但在NUnit测试中没有
本文关键字:但在 NUnit 测试 失败 反序列化 自动化 插件 | 更新日期: 2023-09-27 18:03:34
我有一个自动化插件(实现Extensibility.IDTExtensibility2),用c# 4编写,我试图在其中加载一些(二进制)序列化数据。它在单元测试中工作完美,但在Excel内运行时失败:
Unable to find assembly 'XXX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
at System.Runtime.Serialization.Formatters.Binary.BinaryAssemblyInfo.GetAssembly()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetType(BinaryAssemblyInfo assemblyInfo, String name)
at System.Runtime.Serialization.Formatters.Binary.ObjectMap..ctor(String objectName, String[] memberNames, BinaryTypeEnum[] binaryTypeEnumA, Object[] typeInformationA, Int32[] memberAssemIds, ObjectReader objectReader, Int32 objectId, BinaryAssemblyInfo assemblyInfo, SizedArray assemIdToAssemblyTable)
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record)
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryHeaderEnum binaryHeaderEnum)
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
at
在BinaryFormatter上,我将AssemblyFormat(用于序列化和反序列化)设置如下:
serializationCodec.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
我认为它会忽略这里的版本。
然后认为这可能是由于Excel的"可信位置"的概念,所以我添加了项目的目录并检查了所有子目录,但错误仍然存在。
徒劳地我尝试添加system . runtime . serialize . optionalfieldattribute属性,但它没有帮助。
单元测试可以加载自己生成的序列化文件或在Excel中执行的相同代码,但Excel无法加载序列化的数据,无论它是否进行了实际的序列化。
事实上,Excel不能反序列化它自己序列化的东西,这暗示了这是一个转移注意力的问题,因为它显然可以访问所使用的程序集。
那么问题是为什么Excel反序列化与我的单元测试不同?(或许更重要的是;如何在Excel中实现反序列化?)
谢谢。
我一直在寻找转移注意力的话题,但我认为这是一个版本问题(我已经研究了漏洞和各种各样的问题)。
这实际上是由于奇怪的汇编绑定;尽管自动化插件的DLL可以看到并加载它所依赖的DLL中的类,但当它可以反序列化时,它无法找到必要的程序集-即使反序列化调用来自属于它声称找不到的DLL的类!
解决方案当然是一个hack,但它让我通过了这个,所以如果其他人像我一样被卡住了,这里有一个hack(s):
在类X内部,这取决于类Y和Z各自的项目dll(名为ProjectForX, ProjectForY和ProjectForZ)
private static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
if(args.Name.StartsWith("ProjectForX,")) {
return typeof(X).Assembly;
} else if(args.Name.StartsWith("ProjectForY,")) {
return typeof(Y).Assembly;
} else if(args.Name.StartsWith("ProjectForZ,")) {
return typeof(Z).Assembly;
}
return null;
}
public static X LoadX(string filename)
{
AppDomain currentDomain = AppDomain.CurrentDomain;
ResolveEventHandler handler = new ResolveEventHandler(MyResolveEventHandler);
currentDomain.AssemblyResolve += handler;
try {
Stream stream = new FileStream(@filename, FileMode.Open);
try {
BinaryFormatter deserializer = createBinaryFormatter();
X model = (X)deserializer.Deserialize(stream);
return model;
} finally {
stream.Close();
}
} finally {
currentDomain.AssemblyResolve -= handler;
}
}
基本上,它只是挂钩到resolve事件,并根据所请求的类型名称提供正确的程序集—这不是特别安全(我在程序集描述符中使用逗号以尽量减少任何冲突)。
几乎肯定有一个明确的方法来做到这一点,问题可能只是由于配置不当和我对微软产品的有限经验,特别是c#。
这不会是一个问题,如果我只是建立一个单一的DLL =)