【发布时间】:2011-12-19 17:01:38
【问题描述】:
我有一个运行良好的应用程序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;
这也证明了程序集被有效加载,包括它的所有依赖项,所以第一个问题仍然存在:为什么框架不能自己解决这个问题对我来说是个谜。此外,我无法在使用大致相同结构的第二个应用程序中重现它。
【问题讨论】:
-
这两个文件的名称空间是什么。也许您可以更改它们以匹配并在项目级别与您的使用相匹配。编译器会知道如何引用它,否则听起来您可能需要为它不能或应该找到的方法使用完全限定的命名空间..
-
这个 d.dll 是否也依赖于其他程序集?通过反射加载时,需要满足所有程序集静态引用。
-
@DJKRAZE 你的意思是什么文件?所有有问题的代码都在一个单一的类中,在一个单一的命名空间中。虽然 a.exe 与 b.dll 有不同的命名空间
-
@zenwalker 是的 b.dll 依赖于其他程序集,但它们都已加载(否则代码如何运行?)
-
您可以在同一项目中命名您的程序集以匹配..只要方法名称不冲突,否则您必须完全限定它们..
标签: c# serialization prism system.type