为什么我想这样做一个简短的解释:
我忙着写面向Autodesk Revit Architecture软件测试2010插件我的插件代码是繁琐的极端,因为我必须重新启动欧特克为每个调试会话,手动加载Revit项目,单击加载项选项卡上,然后开始我的插件。 这只是时间太长。
我写了承载了IronPython的解释第二插件。 这样一来,我可以玩与Revit中提供的API。 但最终,该代码在C#重写 - 和调试。
很简单,我想:只要加载从IronPython的脚本插件DLL和锻炼吧。 这并不工作,但一旦加载,我不能在Visual Studio重新编译,因为DLL现在被装载在Revits AppDomain中。
很简单,我想(与StackOverflow上的一点帮助):只要加载一个新的AppDomain的DLL。 唉,RevitAPI对象不能被封送到另一个应用程序域,因为它们不延伸MarshalByRefObject
。
我想我可能会到一些与卷影副本。 ASP.NET似乎是这样。 但是看完MSDN上的文档,似乎创造一个AppDomain的时候,我只能指定。
我可以改变这个当前(默认)的AppDomain? 我可以强制它使用的DLL的卷影副本从一个特定的目录?
我不知道你正在尝试做的,但也有一些过时的方法来打开影拷贝在当前的AppDomain。
AppDomain.CurrentDomain.SetCachePath(@"C:\Cache");
AppDomain.CurrentDomain.SetShadowCopyPath(AppDomain.CurrentDomain.BaseDirectory);
AppDomain.CurrentDomain.SetShadowCopyFiles();
有时候这是不可能的,因为,例如,你正在写一个插件修改Main()方法的代码和它是由一个经理实例化。
在这种情况下,我建议你组装和PDB(在AssemblyResolve事件相关的)复制到一个临时位置,并从那里加载它们与Assembly.LoadFile()(未LoadFrom())。
优点: - 无DLL锁定。 - 每一个目标组件重新编译您的时间可以访问新版本(这就是为什么.LoadFile())。 - 整个组件处于AppDomain.CurrentDomain完全可用。
缺点: - 文件复制是必要的。 - 大会的不能被卸载,因为资源没有释放,可能是不方便。
问候,
PD:此代码的工作。
/// <summary>
/// Loads an assembly without locking the file
/// Note: the assemblys are loaded in current domain, so they are not unloaded by this class
/// </summary>
public class AssemblyLoader : IDisposable
{
private string _assemblyLocation;
private string _workingDirectory;
private bool _resolveEventAssigned = false;
/// <summary>
/// Creates a copy in a new temp directory and loads the copied assembly and pdb (if existent) and the same for referenced ones.
/// Does not lock the given assembly nor pdb and always returns new assembly if recopiled.
/// Note: uses Assembly.LoadFile()
/// </summary>
/// <param name="assemblyOriginalPath"></param>
/// <returns></returns>
public Assembly LoadFileCopy(string assemblyLocation)
{
lock (this)
{
_assemblyLocation = assemblyLocation;
if (!_resolveEventAssigned)
{
_resolveEventAssigned = true;
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(AssemblyFileCopyResolveEvent);
}
// Create new temp directory
_workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(_workingDirectory);
// Generate copy
string assemblyCopyPath = Path.Combine(_workingDirectory, Path.GetFileName(_assemblyLocation));
System.IO.File.Copy(_assemblyLocation, assemblyCopyPath, true);
// Generate copy of referenced assembly debug info (if existent)
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);
}
// Use LoadFile and not LoadFrom. LoadFile allows to load multiple copies of the same assembly
return Assembly.LoadFile(assemblyCopyPath);
}
}
/// <summary>
/// Creates a new copy of the assembly to resolve and loads it
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
/// <returns></returns>
private Assembly AssemblyFileCopyResolveEvent(object sender, ResolveEventArgs args)
{
string referencedAssemblyFileNameWithoutExtension = System.IO.Path.GetFileName(args.Name.Split(',')[0]);
// Generate copy of referenced assembly
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);
// Generate copy of referenced assembly debug info (if existent)
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);
}
// Use LoadFile and not LoadFrom. LoadFile allows to load multiple copies of the same assembly
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;
}
}
}
}
现在有一个的Revit插件动态加载/卸载其他的Revit插件,让你可以改变,重新编译和测试而无需重新打开Revit项目。 我发现它的建筑编码器博客 。 它配备了的Revit SDK。