我目前正在使用以下代码:
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
var name = args.Name + ".dll";
using (var input = Assembly.GetExecutingAssembly()
.GetManifestResourceStream(name)) {
Assembly dll = input != null
? Assembly.Load(input.ToArray())
: null;
return dll;
}
};
在本地的所有实例中,似乎工作正常,但是一个客户端在加载包含的dll时遇到问题(他们没有源代码访问权限)。
在使用此类动态dll加载时,是否存在任何我应该注意的信任问题或陷阱?
中等信任问题似乎不是问题,但是我们生成的dll无论如何都需要完全信任。我想这可能归结为安全权限等等。
在完成文档之后,我再次注意到我跳过的一行,我认为这与我的问题有关。
“从.NET Framework 4开始,为所有程序集引发ResolveEventHandler事件,包括资源程序集。在早期版本中,没有为资源程序集引发事件。如果操作系统是本地化,处理程序可能被多次调用:对于后备链中的每个文化都会调用一次。“
而在3.5中则没有。当我确认时,我会发布更新。
答案 0 :(得分:8)
嗯,没有任何细节,很难诊断;但是,我建议对上面的代码进行一些更改:
args.Name实际上是一个完整的程序集名称,不仅仅是一个简单的名称,还可以包含版本等。将此值传递给AssemblyName的构造函数只解析简单名称。我怀疑这是你遇到的问题。
加载程序集位时,应传播当前域的证据。这可能是你在现场看到的问题,但也许不是。
不要使用正在执行的程序集,通过显式引用该程序集中包含的类型来访问包含该资源的正确程序集。只需在下面的示例中替换“THIS_CLASS”即可。这是我对你所遇问题的根本原因的最佳猜测。
您应该继续将此方法的结果缓存到全局字典中。为什么?可以调用多次加载相同的程序集,并且每次调用时都必须返回相同的程序集实例。您的示例一次又一次地加载程序集。
添加详细日志记录,记录您要查找的程序集,尝试加载的资源名称,加载它的程序集,流是否为null,Load()方法的结果等。< / p>
static Dictionary<String, Assembly> _assemblies = new Dictionary<String, Assembly>(StringComparer.OrdinalIgnoreCase);
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
Assembly dll;
var name = new AssemblyName(args.Name).Name + ".dll";
if(!_assemblies.TryGetValue(name, out dll))
{
Assembly res = typeof(THIS_CLASS).Assembly;
using (var input = res.GetManifestResourceStream(name))
{
if (input == null)
{
LogWrite("Assembly {0} does not contain {1}", res, name);
return null;
}
if (null == (dll = Assembly.Load(input.ToArray(), AppDomain.CurrentDomain.Evidence)))
{
LogWrite("Assembly {0} failed to load.", name);
return null;
}
LogWrite("Loaded assembly {0}.", name);
_assemblies[name] = dll;
return dll;
}
}
return dll;
};