有时候无法修改Main()方法的代码,比如说你正在编写一个插件并且它是由一个管理器实例化的。
在这种情况下,我建议你将程序集和pdb文件(以及AssemblyResolve事件中的依赖项)复制到临时位置,并使用Assembly.LoadFile()(而不是LoadFrom())从那里加载它们。
优点:
-没有dll锁定。
-每次目标程序集重新编译时,您都可以访问新版本(这就是为什么要使用.LoadFile())。
-整个程序集在AppDomain.CurrentDomain中完全可用。
缺点:
-需要复制文件。
-程序集无法卸载,这可能会不方便,因为资源没有被释放。
谢谢。
附注:此代码可以完成工作。
public class AssemblyLoader : IDisposable
{
private string _assemblyLocation;
private string _workingDirectory;
private bool _resolveEventAssigned = false;
public Assembly LoadFileCopy(string assemblyLocation)
{
lock (this)
{
_assemblyLocation = assemblyLocation;
if (!_resolveEventAssigned)
{
_resolveEventAssigned = true;
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(AssemblyFileCopyResolveEvent);
}
_workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(_workingDirectory);
string assemblyCopyPath = Path.Combine(_workingDirectory, Path.GetFileName(_assemblyLocation));
System.IO.File.Copy(_assemblyLocation, assemblyCopyPath, true);
string assemblyPdbPath = _assemblyLocation.Replace(".dll", ".pdb");
if (File.Exists(assemblyPdbPath))
{
string assemblyPdbCopyPath = Path.Combine(_workingDirectory, Path.GetFileName(assemblyPdbPath));
System.IO.File.Copy(assemblyPdbPath, assemblyPdbCopyPath, true);
}
return Assembly.LoadFile(assemblyCopyPath);
}
}
private Assembly AssemblyFileCopyResolveEvent(object sender, ResolveEventArgs args)
{
string referencedAssemblyFileNameWithoutExtension = System.IO.Path.GetFileName(args.Name.Split(',')[0]);
string referencedAssemblyPath = Path.Combine(Path.GetDirectoryName(_assemblyLocation), referencedAssemblyFileNameWithoutExtension + ".dll");
string referencedAssemblyCopyPath = Path.Combine(Path.GetDirectoryName(args.RequestingAssembly.Location), referencedAssemblyFileNameWithoutExtension + ".dll");
System.IO.File.Copy(referencedAssemblyPath, referencedAssemblyCopyPath, true);
string referencedAssemblyPdbPath = Path.Combine(Path.GetDirectoryName(_assemblyLocation), referencedAssemblyFileNameWithoutExtension + ".pdb");
if (File.Exists(referencedAssemblyPdbPath))
{
string referencedAssemblyPdbCopyPath = Path.Combine(Path.GetDirectoryName(args.RequestingAssembly.Location), referencedAssemblyFileNameWithoutExtension + ".pdb");
System.IO.File.Copy(referencedAssemblyPath, referencedAssemblyCopyPath, true);
}
return Assembly.LoadFile(referencedAssemblyCopyPath);
}
public void Dispose()
{
Dispose(true);
}
private void Dispose(bool disposing)
{
if (disposing)
{
if (_resolveEventAssigned)
{
AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler(AssemblyFileCopyResolveEvent);
_resolveEventAssigned = false;
}
}
}
}
SetShadowCopyFiles()
之前加载它们。 - lubos hasko