Revit 自定义事务进行自动管理事务DBTrans实现

发布时间 2023-10-27 13:13:41作者: 百年一梦

第一步:自定义事务对象

自定义事务对象
    /// <summary>
    /// 自定义事务
    /// </summary>
    public class DBTrans : IDisposable
    {
        #region 私有字段

        private bool disposedValue;

        private bool _commit;
        /// <summary>
        /// 事务栈
        /// </summary>
        private static readonly Stack<DBTrans> dBTrans = new Stack<DBTrans>();
        #endregion

        #region 公开属性
        /// <summary>
        /// 返回当前事务
        /// </summary>
        public static DBTrans Top => dBTrans.Peek();
        /// <summary>
        /// 事务管理器
        /// </summary>
        public Transaction Trans { get; private set; }
        /// <summary>
        /// UI应用
        /// </summary>
        public UIApplication UIApplication { get; private set; }
        /// <summary>
        /// 应用
        /// </summary>
        public Application Application { get; private set; }
        /// <summary>
        /// UI文档
        /// </summary>
        public UIDocument UIDocument { get; private set; }
        /// <summary>
        /// 文档
        /// </summary>
        public Document Document { get; private set; }
        #endregion

        #region 构造函数
        /// <summary>
        /// 默认构造函数,默认为打开当前文档,默认提交事务
        /// </summary>
        /// <param name="doc">要打开的文档</param>
        /// <param name="commit">事务是否提交</param>
        public DBTrans(Document doc, bool commit = true)
        {
            this.Document = doc;
            this.UIApplication = new UIApplication(this.Document.Application);
            this.UIDocument = this.UIApplication.ActiveUIDocument;
            this.Application = this.UIApplication.Application;
            Init(commit);
        }

        /// <summary>
        /// 默认构造函数,默认为打开当前文档,默认提交事务
        /// </summary>
        /// <param name="doc">要打开的文档</param>
        /// <param name="commit">事务是否提交</param>
        public DBTrans(Document doc, string name, bool commit = true)
        {
            this.Document = doc;
            this.UIApplication = new UIApplication(this.Document.Application);
            this.UIDocument = this.UIApplication.ActiveUIDocument;
            this.Application = this.UIApplication.Application;
            Init(commit,name);
        }
        /// <summary>
        /// 初始化事务及事务队列、提交模式
        /// </summary>
        /// <param name="commit">提交模式</param>
        private void Init(bool commit,string name=null)
        {

            if (name == null) name = Guid.NewGuid().ToString("D");
            Trans = new Transaction(Document,name);
            Trans.Start();
            _commit = commit;
            dBTrans.Push(this);
        }

        #endregion
        #region 获取元素
        /// <summary>
        /// 通过Id获取元素
        /// </summary>
        /// <typeparam name="T">元素类型</typeparam>
        /// <param name="id">元素Id</param>
        /// <returns>元素对象</returns>
        public T GetElement<T>(ElementId id) where T : Element
        {
            return Document.GetElement(id) as T;
        }
        /// <summary>
        /// 通过引用获取元素
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="reference"></param>
        /// <returns></returns>
        public T GetElement<T>(Reference reference) where T : Element
        {
            return Document.GetElement(reference) as T;
        }
        /// <summary>
        /// 通过唯一Id获取元素对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="uniqueId"></param>
        /// <returns></returns>
        public T GetElement<T>(string uniqueId) where T : Element
        {
            return Document.GetElement(uniqueId) as T;
        }
        #endregion



        #region idispose接口相关函数
        /// <summary>
        /// 事务回滚
        /// </summary>
        public void Abort()
        {
            Trans.RollBack();
        }
        /// <summary>
        /// 事务提交
        /// </summary>
        public void Commit()
        {
            if (_commit)
            {
                Trans.Commit();
            }
            else
            {
                Abort();
            }

        }
        /// <summary>
        /// 事务处理
        /// </summary>
        /// <param name="disposing">是否处理</param>
        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // 释放托管状态(托管对象)
                    Commit();
                    dBTrans.Pop();
                    if (Trans.IsValidObject)
                    {
                        Trans.Dispose();
                    }
                }
                // 释放未托管的资源(未托管的对象)并替代终结器
                // 将大型字段设置为 null
                disposedValue = true;
            }
        }
        /// <summary>
        /// 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
        /// </summary>
        ~DBTrans()
        {
            // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
            Dispose(disposing: false);
        }
        /// <summary>
        /// 事务处理
        /// </summary>
        public void Dispose()
        {
            // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }
        #endregion
    }

第二步:使用using关键字使用事务对象

使用自定义事务
    /// <summary>
    /// 扩展数据测试
    /// </summary>
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    public class TSTCmd2 : IExternalCommand
    {

        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIDocument uidoc = commandData.Application.ActiveUIDocument;
            Document doc = uidoc.Document;
            var temp = uidoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
            Wall el = doc.GetElement(temp) as Wall;
            //定义事务对象
            using (DBTrans dBTrans = new DBTrans(doc))
            {
                Ent ent = new Ent() { A = 10, B = "测试", D = new Dictionary<string, int>() { { "K1", 1 }, { "K2", 2 } }, L = new List<int>() { 1, 2 }};
                el.SetEntity(EntityEx.Build<Ent>("扩展数据1", ent));
                ent = new Ent() { A = 10, B = "测试2", D = new Dictionary<string, int>() { { "K1", 1 }, { "K2", 2 } }, L = new List<int>() { 1, 2 },E = new Dictionary<int, int>() {{ 1,1} ,{ 2,2} } };
                el.SetEntity(EntityEx.Build<Ent>("扩展数据2", ent));
            }
            return Result.Succeeded;
        }
    }