我正在尝试将程序集(dll)加载到AppDomain中并调用入口点。 (基本上将包引导到Azure环境中)我一直在关注这篇SO文章(How do I create an application domain and run my application in it?),我认为我做得对,但我遇到了一些问题。
我已经在这里使用了几篇文章来帮助我,但我仍然按照Unable to load executing assembly into new AppDomain, FileNotFoundException中的描述运行FileNotFoundException
。我的问题是解决方案不起作用。我试图执行的程序集存在于不同的位置。所以ApplicationBase
需要是我试图执行的程序集的文件夹。
var otherType = typeof(BootstrapProxy);
var domaininfo = new AppDomainSetup
{
ConfigurationFile = executingAssembly + ".config",
ApplicationBase = _root
};
Evidence adevidence = AppDomain.CurrentDomain.Evidence;
_domain = AppDomain.CreateDomain(_type.ToString(), adevidence, domaininfo);
_domain.AssemblyResolve += (sender, args) =>
{
var lookupPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (lookupPath == null) return null;
var assemblyname = new AssemblyName(args.Name).Name;
var assemblyFileName = Path.Combine(lookupPath, assemblyname + ".dll");
var assembly = Assembly.LoadFrom(assemblyFileName);
return assembly;
};
var proxy = _domain.CreateInstanceAndUnwrap(otherType.Assembly.FullName, otherType.FullName) as BootstrapProxy;
最后一行抛出异常,而AssemblyResolve事件永远不会触发(通过在var lookupPath
行放置一个断点来确定。
我还尝试使用与上面相同的处理程序的AppDomain.CurrentDomain.AssemblyResolve
事件,但没有运气。我也尝试在BootstrapProxy
类中创建相同的处理程序。
我认为我正在做这件事,但要注意第一段,所以如果我完全偏离基础,我不反对以不同的方式做事。
更新:
我更改了代码以强制将程序集加载到新的appdomain中,但仍然存在问题。
var otherType = typeof(BootstrapProxy);
var domaininfo = new AppDomainSetup
{
ConfigurationFile = executingAssembly + ".config",
ApplicationBase = _root
};
Evidence adevidence = AppDomain.CurrentDomain.Evidence;
_domain = AppDomain.CreateDomain(_type.ToString(), adevidence, domaininfo);
var deps = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
foreach (var dep in deps)
{
var lookupPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (lookupPath == null) continue;
var assemblyname = new AssemblyName(dep.Name).Name;
var assemblyFileName = Path.Combine(lookupPath, assemblyname + ".dll");
if (File.Exists(assemblyFileName))
_domain.Load(File.ReadAllBytes(assemblyFileName));
}
_domain.Load(File.ReadAllBytes(Assembly.GetExecutingAssembly().Location));
var sl = _domain.GetAssemblies().ToArray();
var proxy = _domain.CreateInstanceAndUnwrap(otherType.Assembly.FullName, otherType.FullName) as BootstrapProxy;
sl
显示所有dll,包括FileNotFoundException
中引用的dll都已加载到新的appdomain中。
public class BootstrapProxy : MarshalByRefObject
{
public void Main()
{
Console.WriteLine("Magic happened.");
}
}
更新2:
我改变了它:
var deps = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
foreach (var dep in deps)
{
var lookupPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (lookupPath == null) continue;
var assemblyname = new AssemblyName(dep.Name).Name;
var assemblyFileName = Path.Combine(lookupPath, assemblyname + ".dll");
if (File.Exists(assemblyFileName))
File.Copy(assemblyFileName, Path.Combine(_root, assemblyname + ".dll"));
}
File.Copy(Assembly.GetExecutingAssembly().Location, Path.Combine(_root, Path.GetFileName(Assembly.GetExecutingAssembly().Location)));
var otherType = typeof(BootstrapProxy);
var domaininfo = new AppDomainSetup
{
ConfigurationFile = executingAssembly + ".config",
ApplicationBase = _root
};
Evidence adevidence = AppDomain.CurrentDomain.Evidence;
_domain = AppDomain.CreateDomain(_type.ToString(), adevidence, domaininfo);
var proxy = _domain.CreateInstanceAndUnwrap(otherType.Assembly.FullName, otherType.FullName) as BootstrapProxy;
if (proxy != null)
{
proxy.Main();
}
这种复制程序集及其对新AppDomain的ApplicationBase的引用的方法并不理想,因为有一些常见的引用,我最终可能会遇到版本冲突和其他问题。
答案 0 :(得分:1)
只是一个猜测,但问题在于:
var otherType = typeof(BootstrapProxy);
通过执行此操作,您将该程序集加载到调用的appdomain中。由于初始化,它尝试加载调用域的查找路径中不存在的程序集。 KABOOM!
解决这个问题:
请使用其完全限定名称引用otherType
,并将程序集名称作为字符串传递。 (我想你可能只是使用该类型的FQN而逃脱了)
另外。对于appdomain之外的程序集,您不应该真正处理AssemblyResolve
。