Revit Api 加载命令 - 自动重新加载

Revit Api Load Command - Auto Reload

我正在使用 revit api,它的问题之一是它在命令 运行 后锁定 .dll。必须先退出 revit 才能重建命令,非常耗时。

经过一些研究,我在 GitHub 上发现了这个 post,它将命令 .dll 流式传输到内存中,从而将其隐藏在 Revit 中。让你随心所欲地重建VS项目

AutoReload Class impliments revit IExteneralCommand Class 这是 link 进入 Revit 程序。

但是 AutoReload class 对 revit 隐藏了实际的源 DLL。所以revit无法锁定DLL,让我们重建源文件。

唯一的问题是我不知道如何实现它,并让revit 执行命令。我想我的C#常识还是太有限了。

我在 RevitAddin.addin 清单中创建了一个指向 AutoReload Method 命令的条目,但没有任何反应。

我已尝试遵循 posted 代码中的所有注释,但似乎没有任何效果;找不到开发人员的联系方式。

发现于: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")
    {
    }
    }

}

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

转到 Revit Developer Center 并下载 Revit SDK,unzip/install 它,检查 \Revit 2016 SDK\Add-In Manager 文件夹。使用此工具,您可以 load/reload DLL 而无需修改代码。

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

以上代码的使用方法:

  1. 创建一个新的 VS class 项目;随便命名(例如 AutoLoad)
  2. 在命名空间区域之间复制并粘贴以上代码
  3. 参考 revitapi.dll & revitapiui.dll
  4. 向下滚动到 AutoReloadExample class 并将路径替换为指向 你的 dll
  5. 将 "Mine.ExampleCommand" 替换为您的插件 namespace.mainclass
  6. 构建解决方案
  7. 创建一个 .addin 清单来指向这个新的加载器(例如 AutoLoad.dll)
  8. 您的 .addin 应该包括 "FullClassName" AutoLoad.AutoReloadExample

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

干杯