gpt4 book ai didi

System.Type 的 C# 反序列化从加载的程序集中抛出类型

转载 作者:太空狗 更新时间:2023-10-29 20:25:13 25 4
gpt4 key购买 nike

我有一个运行良好的应用程序 a.exe 并加载了一个程序集 b.dll,如果重要的话,它是一个 Prism 模块。此 dll 从不在路径中但在 a.exe 所在目录中的目录中加载。

程序集的加载由 Prism 完成,设置如下:

public class MyModuleCatalog : ComposablePartCatalog
{
private readonly AggregateCatalog _catalog;

public MyModuleCatalog()
{
//directory Modules is not in the path, but all
//dependencies of b.dll are, so b.dll gets loaded fine
var asmCat = new AssemblyCatalog( "Modules/b.dll" );
_catalog.Catalogs.Add( asmCat );
}

public override IQueryable<ComposablePartDefinition> Parts
{
get { return _catalog.Parts; }
}
}

class BootStrapper : MefBootstrapper
{
....
protected override void ConfigureAggregateCatalog()
{
base.ConfigureAggregateCatalog();

AggregateCatalog.Catalogs.Add( new AssemblyCatalog( Assembly.GetExecutingAssembly() ) );
AggregateCatalog.Catalogs.Add( new MyModuleCatalog() );
}
....
}

b.dll中有一个类ImInB:

[Export]
public class ImInB
{
public void DoIt()
{
try
{
var stream = new MemoryStream();
//using System.Runtime.Serialization.Formatters.
var formatter = new BinaryBinaryFormatter();

//serialize our type
formatter.Serialize( stream, this.GetType() );

//get it back
stream.Position = 0;
var obj = formatter.Deserialize( stream ); //this throws??
}
catch( Exception e )
{
}
}
}

这只是示例代码,是将设置加载/保存到数据库的持久性框架的一部分。对象的类型始终是序列化的,并用作数据库的键。反序列化后,类型将被检索回来,作为对加载对象的双重检查。该函数从 a.exe 调用:

container.GetExportedValue<ImInB>().DoIt();

反序列化类型时抛出的异常(前两行已成功序列化)是:

"Could not load file or assembly 'b.dll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
or one of its dependencies. The system cannot find the file specified."

问题:

  • 这怎么可能?该函数是从 dll 中调用的,但说找不到该 dll。
  • 我该如何解决这个问题?我怎么告诉 Deserialize 嘿,dll 已经加载了,不要去寻找它

更新我的第二个问题基本由 Felix K 回答;下面的代码解决了这个问题:

public static class AssemblyResolverFix
{
//Looks up the assembly in the set of currently loaded assemblies,
//and returns it if the name matches. Else returns null.
public static Assembly HandleAssemblyResolve( object sender, ResolveEventArgs args )
{
foreach( var ass in AppDomain.CurrentDomain.GetAssemblies() )
if( ass.FullName == args.Name )
return ass;
return null;
}
}

//in main
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolverFix.HandleAssemblyResolve;

这也证明程序集已有效加载,包括它的所有依赖项,所以第一个问题仍然存在:框架无法自行解决这个问题对我来说是个谜。此外,我无法在使用大致相同结构的第二个应用程序中重现它。

最佳答案

我不知道为什么当 dll 已经加载时会发生这种情况,但我认为这与序列化本身无关,对我来说它看起来像是 .NET 错误。

这可能会对您有所帮助,或者为您指明正确的方向:

AppDomain current = AppDomain.CurrentDomain;
current.AssemblyResolve += new ResolveEventHandler(HandleAssemblyResolve);

static Assembly HandleAssemblyResolve(object sender, ResolveEventArgs args)
{
/* Load the assembly specified in 'args' here and return it,
if the assembly is already loaded you can return it here */
}

每次缺少 dll 时都会调用 resolve 方法,因此当您的 dll 丢失时也会发生这种情况。 dotNET 找不到它,因为它在“Modules”文件夹中,所以您必须自己解析引用。

关于System.Type 的 C# 反序列化从加载的程序集中抛出类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8564761/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com