2015-11-04 163 views
0

我正在使用revit api,其中一个问题是它在命令运行后锁定.dll。在命令可以重建之前必须退出修改,这非常耗时。Revit Api加载命令 - 自动重装

经过一番研究,我发现这个职位在GitHub上,该.dll文件流的命令到内存中,从而从Revit隐藏它。让您尽可能多地重建VS项目。

的自动重类impliments所述的Revit IExteneralCommand类,这是链接到节目的Revit。

但是AutoReload类从revit中隐藏了实际的源DLL。所以revit不能锁定DLL并让我们重建源文件。

唯一的问题是我无法弄清楚如何实现它,并且有Revit中执行命令。我想我的C#常识还是太有限了。

我创造了RevitAddin.addin清单指向自动重载方法命令条目,但没有任何反应。

我试着按照张贴的代码的所有意见,但似乎没有任何工作;并且没有运气找到开发者的联系人。

找到在:https://gist.github.com/6084730.git

using System; 

namespace Mine 
{ 
    // helper class 
    public class PluginData 
    { 
     public DateTime _creation_time; 
     public Autodesk.Revit.UI.IExternalCommand _instance; 

    public PluginData(Autodesk.Revit.UI.IExternalCommand instance) 
    { 
     _instance = instance; 
    } 
} 

// 
// Base class for auto-reloading external commands that reside in other dll's 
// (that Revit never knows about, and therefore cannot lock) 
// 
public class AutoReload : Autodesk.Revit.UI.IExternalCommand 
{ 
    // keep a static dictionary of loaded modules (so the data persists between calls to Execute) 
    static System.Collections.Generic.Dictionary<string, PluginData> _dictionary; 

    String _path; // to the dll 
    String _class_full_name; 

    public AutoReload(String path, String class_full_name) 
    { 
     if (_dictionary == null) 
     { 
      _dictionary = new System.Collections.Generic.Dictionary<string, PluginData>(); 
     } 
     if (!_dictionary.ContainsKey(class_full_name)) 
     { 
      PluginData data = new PluginData(null); 
      _dictionary.Add(class_full_name, data); 
     } 
     _path = path; 
     _class_full_name = class_full_name; 
    } 

    public Autodesk.Revit.UI.Result Execute(
     Autodesk.Revit.UI.ExternalCommandData commandData, 
     ref string message, 
     Autodesk.Revit.DB.ElementSet elements) 
    { 
     PluginData data = _dictionary[_class_full_name]; 
     DateTime creation_time = new System.IO.FileInfo(_path).LastWriteTime; 
     if (creation_time.CompareTo(data._creation_time) > 0) 
     { 
      // dll file has been modified, or this is the first time we execute this command. 
      data._creation_time = creation_time; 
      byte[] assembly_bytes = System.IO.File.ReadAllBytes(_path); 
      System.Reflection.Assembly assembly = System.Reflection.Assembly.Load(assembly_bytes); 
      foreach (Type type in assembly.GetTypes()) 
      { 
       if (type.IsClass && type.FullName == _class_full_name) 
       { 
        data._instance = Activator.CreateInstance(type) as Autodesk.Revit.UI.IExternalCommand; 
        break; 
       } 
      } 
     } 
     // now actually call the command 
     return data._instance.Execute(commandData, ref message, elements); 
    } 
} 

// 
// Derive a class from AutoReload for every auto-reloadable command. Hardcode the path 
// to the dll and the full name of the IExternalCommand class in the constructor of the base class. 
// 
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] 
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] 
public class AutoReloadExample : AutoReload 
{ 
    public AutoReloadExample() 
     : base("C:\\revit2014plugins\\ExampleCommand.dll", "Mine.ExampleCommand") 
    { 
    } 
    } 

} 
+0

为什么不买SSD?玩弄'Assembly.Loadxxx'只会给你更多的问题,而不是解决问题。 – Maxence

回答

2

还有一个更简单的方法:加载项管理器

转到Revit Developer Center和下载的Revit SDK,解压缩/安装,检查在\ Revit 2016 SDK \ Add-In Manager文件夹。有了这个工具,您可以加载/重新加载DLL,而无需修改代码。

也有这个blog post一些额外的信息。

+0

你应该注意到这些方法的唯一的一点是,如果在几个不同的时间加载同一个类,序列化可能会产生问题。 – Matt

+0

我看着添加管理器;我认为这只是运行命令的几个步骤。但我想如果我只是用它来开发一个新的命令它并不那么糟糕。 – Ryan

0

这是你如何使用上面的代码:

  1. VS类项目中创建一个新的;使用任何名字(例如自动加载)
  2. 复制粘贴&在上面的代码之间的命名空间区域
  3. 滚动
  4. 参考revitapi.dll & revitapiui.dll到AutoReloadExample类和替换路径指向 您dll的
  5. 替换 “Mine.ExampleCommand” 用你的插件namespace.mainclass
  6. 构建解决方案
  7. 创建.addin清单指向这个新加载器(如 AutoLoad.dll)
  8. 您.addin应包括“FullClassName” AutoLoad.AutoReloadExample

此方法使用反射来创建你的插件的实例,并防止Revit中锁定您的dll文件!您可以添加更多的命令,只需添加像AutoReloadExample这样的新类,并将它们指向单独的.addin文件即可。

干杯