527 lines
17 KiB
C#
527 lines
17 KiB
C#
|
|
|
|||
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Linq;
|
|||
|
|
|
|||
|
|
using Autodesk.Revit.DB;
|
|||
|
|
using Autodesk.Revit.DB.Architecture;
|
|||
|
|
|
|||
|
|
namespace Szmedi.Toolkit.RvExtensions;
|
|||
|
|
|
|||
|
|
public static class DocumentExtensions
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 文档的收集器
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="document"></param>
|
|||
|
|
public static FilteredElementCollector OfCollector(this Document document) => document == null ? throw new ArgumentNullException(nameof(document), "文档为空") : new(document);
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 类型的元素集合
|
|||
|
|
/// </summary>
|
|||
|
|
/// <typeparam name="T"></typeparam>
|
|||
|
|
/// <param name="doc"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public static FilteredElementCollector QueryElementsByType<T>(this Document doc)
|
|||
|
|
where T : Element
|
|||
|
|
{
|
|||
|
|
return doc.OfCollector().OfClass(typeof(T));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 收集特定类别
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="doc"></param>
|
|||
|
|
/// <param name="builtInCategory"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public static FilteredElementCollector QueryElementsByCategory(this Document doc, BuiltInCategory builtInCategory)
|
|||
|
|
{
|
|||
|
|
return doc.OfCollector().OfCategory(builtInCategory);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 收集特定类型
|
|||
|
|
/// </summary>
|
|||
|
|
/// <typeparam name="T"></typeparam>
|
|||
|
|
/// <param name="doc"></param>
|
|||
|
|
/// <param name="builtInCategory"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public static FilteredElementCollector QueryElementsByTypeAndCategory<T>(this Document doc, BuiltInCategory builtInCategory)
|
|||
|
|
where T : Element
|
|||
|
|
{
|
|||
|
|
return doc.OfCollector().OfClass(typeof(T)).OfCategory(builtInCategory);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static FilteredElementCollector OfCollector(this View view)
|
|||
|
|
{
|
|||
|
|
//if (view == null)
|
|||
|
|
//{
|
|||
|
|
// throw new ArgumentNullException(nameof(view));
|
|||
|
|
//}
|
|||
|
|
//if (!view.IsTemplate)
|
|||
|
|
//{
|
|||
|
|
// return new FilteredElementCollector(view.doc, view.Id);
|
|||
|
|
//}
|
|||
|
|
return FilteredElementCollector.IsViewValidForElementIteration(view.Document, view.Id)
|
|||
|
|
? new FilteredElementCollector(view.Document, view.Id)
|
|||
|
|
: throw new ArgumentException("当前视图不可应用收集器");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 收集当前平面视图的某类图元
|
|||
|
|
/// </summary>
|
|||
|
|
/// <typeparam name="T"></typeparam>
|
|||
|
|
/// <param name="view"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public static FilteredElementCollector QueryInstancesByType<T>(this View view)
|
|||
|
|
where T : Element
|
|||
|
|
{
|
|||
|
|
return view.OfCollector().OfClass(typeof(T)).WhereElementIsNotElementType();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 收集当前平面视图的某类别图元
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="view"></param>
|
|||
|
|
/// <param name="builtInCategory"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public static FilteredElementCollector QueryElementsByCategoryInView(this View view, BuiltInCategory builtInCategory)
|
|||
|
|
{
|
|||
|
|
return view.OfCollector().OfCategory(builtInCategory).WhereElementIsNotElementType();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 收集当前平面视图的某类图元
|
|||
|
|
/// </summary>
|
|||
|
|
/// <typeparam name="T"></typeparam>
|
|||
|
|
/// <param name="view"></param>
|
|||
|
|
/// <param name="builtInCategory"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public static FilteredElementCollector QueryElementsByTypeAndCategory<T>(this View view, BuiltInCategory builtInCategory)
|
|||
|
|
where T : Element
|
|||
|
|
{
|
|||
|
|
return view.OfCollector().OfClass(typeof(T)).OfCategory(builtInCategory).WhereElementIsNotElementType();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 过滤项目文件独立模型元素,包含依附在主体上的元素,如楼板边缘、屋顶边缘、墙饰条、封檐板,檐沟等等
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns>元素集合</returns>
|
|||
|
|
public static FilteredElementCollector OfParentModelCollector(this Document doc)
|
|||
|
|
{
|
|||
|
|
var col = doc.OfCollector()
|
|||
|
|
.WhereElementIsNotElementType()
|
|||
|
|
.Where(
|
|||
|
|
e => e is TopographySurface ||
|
|||
|
|
e is DirectShape ||
|
|||
|
|
(e.CanHaveTypeAssigned()
|
|||
|
|
&& e.IsValidObject
|
|||
|
|
&& e.HasPhases()
|
|||
|
|
&& e.ArePhasesModifiable()
|
|||
|
|
&& e.get_BoundingBox(null) != null
|
|||
|
|
&& e.Category is { CategoryType: CategoryType.Model }
|
|||
|
|
&& (e is HostObject || e.Category.Parent == null)
|
|||
|
|
&& e is not Panel
|
|||
|
|
&& e is not Mullion
|
|||
|
|
&& e is not RevitLinkInstance)
|
|||
|
|
).Select(e => e.Id).ToList();
|
|||
|
|
if (col.Count == 0)
|
|||
|
|
{
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
return new FilteredElementCollector(doc, col).WhereElementIsNotElementType();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 过滤项目文件的所有模型元素
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns>元素集合</returns>
|
|||
|
|
public static FilteredElementCollector OfAllModelCollector(this Document doc)
|
|||
|
|
{
|
|||
|
|
if (doc == null)
|
|||
|
|
{
|
|||
|
|
throw new ArgumentNullException(nameof(doc), "文档为空");
|
|||
|
|
}
|
|||
|
|
var col = doc.OfCollector()
|
|||
|
|
.WhereElementIsNotElementType()
|
|||
|
|
.Where(
|
|||
|
|
e => e is TopographySurface ||
|
|||
|
|
e is DirectShape ||
|
|||
|
|
(e.CanHaveTypeAssigned() &&
|
|||
|
|
e.IsValidObject &&
|
|||
|
|
e.HasPhases() &&
|
|||
|
|
e.ViewSpecific == false &&
|
|||
|
|
e.Category is { CategoryType: CategoryType.Model, AllowsBoundParameters: true } &&
|
|||
|
|
e.get_BoundingBox(null) != null &&
|
|||
|
|
e is not RevitLinkInstance)).Select(e => e.Id).ToList();
|
|||
|
|
if (col.Count == 0)
|
|||
|
|
{
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
return new FilteredElementCollector(doc, col).WhereElementIsNotElementType();
|
|||
|
|
}
|
|||
|
|
///// <summary>
|
|||
|
|
///// 获取所有最高层级的模型元素,不包含子模型
|
|||
|
|
///// </summary>
|
|||
|
|
///// <param name="doc"></param>
|
|||
|
|
///// <returns></returns>
|
|||
|
|
//public static IEnumerable<Element> OfModelElements(this Document doc)
|
|||
|
|
//{
|
|||
|
|
// return doc.OfCollector()
|
|||
|
|
// .WhereElementIsNotElementType()
|
|||
|
|
// .Where(
|
|||
|
|
// e => e is TopographySurface || (
|
|||
|
|
// e.CanHaveTypeAssigned()
|
|||
|
|
// && e.IsValidObject
|
|||
|
|
// && e.get_BoundingBox(null) != null
|
|||
|
|
// && e.HasPhases()
|
|||
|
|
// && e.ViewSpecific == false
|
|||
|
|
// && e.Category is { Parent: null, CategoryType: CategoryType.FacilityNumber, AllowsBoundParameters: true }
|
|||
|
|
// && e is not Panel
|
|||
|
|
// && e is not Mullion
|
|||
|
|
// && e is not RevitLinkInstance)
|
|||
|
|
// );
|
|||
|
|
//}
|
|||
|
|
///// <summary>
|
|||
|
|
///// 所有元素不包括幕墙嵌板,幕墙竖梃、依附图元等等
|
|||
|
|
///// </summary>
|
|||
|
|
///// <param name="doc"></param>
|
|||
|
|
///// <returns></returns>
|
|||
|
|
//public static FilteredElementCollector OfModelCollector(this Document doc)
|
|||
|
|
//{
|
|||
|
|
// if (doc == null)
|
|||
|
|
// {
|
|||
|
|
// throw new ArgumentNullException(nameof(doc), "文档为空");
|
|||
|
|
// }
|
|||
|
|
// var li = doc.OfCollector().WhereElementIsNotElementType()
|
|||
|
|
// .Where(
|
|||
|
|
// e => e is TopographySurface ||
|
|||
|
|
// (e.CanHaveTypeAssigned() &&
|
|||
|
|
// e.HasPhases() &&
|
|||
|
|
// e.Category is { Parent: null, CategoryType: CategoryType.FacilityNumber } &&
|
|||
|
|
// e is not Panel &&
|
|||
|
|
// e is not Mullion &&
|
|||
|
|
// e is not RevitLinkInstance)).Select(e => e.Id).ToList();
|
|||
|
|
// return new FilteredElementCollector(doc, li).WhereElementIsNotElementType();
|
|||
|
|
//}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取对应类型的元素收集器
|
|||
|
|
/// </summary>
|
|||
|
|
/// <typeparam name="T"></typeparam>
|
|||
|
|
/// <param name="doc"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public static IEnumerable<T> OfType<T>(this Document doc)
|
|||
|
|
where T : Element => doc.OfCollector().OfClass(typeof(T)).OfType<T>();
|
|||
|
|
public static FilteredElementCollector OfClass<T>(this Document doc)
|
|||
|
|
where T : Element
|
|||
|
|
{
|
|||
|
|
return doc.OfCollector().OfClass(typeof(T));
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 射线法查找所有的Element
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="doc">Dcument</param>
|
|||
|
|
/// <param name="filter">例如:ElementClassFilter filter = new ElementClassFilter(typeof(CableTray))</param>
|
|||
|
|
/// <param name="targetRef">目标对象</param>
|
|||
|
|
/// <param name="center">射源</param>
|
|||
|
|
/// <param name="direction">方向</param>
|
|||
|
|
/// <returns>返回该射线</returns>
|
|||
|
|
public static IList<Element> XRayFindAll(
|
|||
|
|
this Document doc,
|
|||
|
|
ElementFilter filter,
|
|||
|
|
FindReferenceTarget targetRef,
|
|||
|
|
XYZ center,
|
|||
|
|
XYZ direction
|
|||
|
|
)
|
|||
|
|
{
|
|||
|
|
FilteredElementCollector collector = new(doc);
|
|||
|
|
Func<View3D, bool> isNotTemplate = v3 => !v3.IsTemplate;
|
|||
|
|
var view3D = collector.OfClass(typeof(View3D)).Cast<View3D>().First(isNotTemplate);
|
|||
|
|
ReferenceIntersector refIntersector = new(filter, targetRef, view3D);
|
|||
|
|
var refWithContexts = refIntersector.Find(center, direction);
|
|||
|
|
if (null == refWithContexts)
|
|||
|
|
{
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
IList<Element> resultElements = [];
|
|||
|
|
foreach (var rwc in refWithContexts)
|
|||
|
|
{
|
|||
|
|
var reference = rwc.GetReference();
|
|||
|
|
var hitElement = doc.GetElement(reference);
|
|||
|
|
if (hitElement != null)
|
|||
|
|
{
|
|||
|
|
resultElements.Add(hitElement);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return resultElements;
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取标高范围框
|
|||
|
|
/// </summary>
|
|||
|
|
/// <remarks>最低标高除了包含以上部分,还包含以下部分,最高标高包含以上部分</remarks>
|
|||
|
|
/// <param name="doc"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public static Dictionary<Level, Outline> GetLevelRanges(this Document doc)
|
|||
|
|
{
|
|||
|
|
var levels = doc.OfType<Level>().Cast<Level>().OrderBy(l => l.Elevation).ToList();
|
|||
|
|
Dictionary<Level, Outline> levelOutlines = [];
|
|||
|
|
//获取标高范围
|
|||
|
|
for (var i = 0; i < levels.Count; i++)
|
|||
|
|
{
|
|||
|
|
var baseLevel = levels[i];
|
|||
|
|
XYZ min = new(double.MinValue, double.MinValue, baseLevel.Elevation);
|
|||
|
|
XYZ max;
|
|||
|
|
Outline outline;
|
|||
|
|
if (i == 0)
|
|||
|
|
{
|
|||
|
|
min = new XYZ(double.MinValue, double.MinValue, double.MinValue);
|
|||
|
|
var topLevel = levels[i + 1];
|
|||
|
|
max = new XYZ(double.MaxValue, double.MaxValue, topLevel.Elevation);
|
|||
|
|
outline = new Outline(min, max);
|
|||
|
|
}
|
|||
|
|
else if (i < levels.Count - 1)
|
|||
|
|
{
|
|||
|
|
var topLevel = levels[i + 1];
|
|||
|
|
max = new XYZ(double.MaxValue, double.MaxValue, topLevel.Elevation);
|
|||
|
|
outline = new Outline(min, max);
|
|||
|
|
}
|
|||
|
|
else//最后一个标高以上
|
|||
|
|
{
|
|||
|
|
max = new XYZ(double.MaxValue, double.MaxValue, double.MaxValue);
|
|||
|
|
outline = new Outline(min, max);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
levelOutlines.Add(baseLevel, outline);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return levelOutlines;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 射线法查找最近的Element
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="doc">Dcument</param>
|
|||
|
|
/// <param name="filter">例如:ElementClassFilter filter = new ElementClassFilter(typeof(CableTray))</param>
|
|||
|
|
/// <param name="targetRef">目标对象</param>
|
|||
|
|
/// <param name="center">射源</param>
|
|||
|
|
/// <param name="direction">方向</param>
|
|||
|
|
/// <param name="hitElement">被击中的Element</param>
|
|||
|
|
/// <returns>返回该射线</returns>
|
|||
|
|
public static Line XRayFindNearest(
|
|||
|
|
this Document doc,
|
|||
|
|
ElementFilter filter,
|
|||
|
|
FindReferenceTarget targetRef,
|
|||
|
|
XYZ center,
|
|||
|
|
XYZ direction,
|
|||
|
|
ref Element hitElement
|
|||
|
|
)
|
|||
|
|
{
|
|||
|
|
FilteredElementCollector collector = new(doc);
|
|||
|
|
var view3D = collector.OfClass(typeof(View3D)).Cast<View3D>().First(v3 => !v3.IsTemplate);
|
|||
|
|
var rwc = new ReferenceIntersector(filter, targetRef, view3D).FindNearest(center, direction);
|
|||
|
|
if (null == rwc)
|
|||
|
|
{
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var reference = rwc.GetReference();
|
|||
|
|
var intersection = reference.GlobalPoint;
|
|||
|
|
hitElement = doc.GetElement(reference);
|
|||
|
|
Line result = null;
|
|||
|
|
if (!center.IsAlmostEqualTo(intersection))
|
|||
|
|
{
|
|||
|
|
result = Line.CreateBound(center, intersection);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
hitElement = null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static TResult Invoke<TResult>(this Document doc, Func<Transaction, TResult> func, string name = "default")
|
|||
|
|
{
|
|||
|
|
using var tr = new Transaction(doc, name);
|
|||
|
|
tr.Start();
|
|||
|
|
|
|||
|
|
var result = func(tr);
|
|||
|
|
|
|||
|
|
var status = tr.GetStatus();
|
|||
|
|
switch (status)
|
|||
|
|
{
|
|||
|
|
case TransactionStatus.Started:
|
|||
|
|
tr.Commit();
|
|||
|
|
return result;
|
|||
|
|
|
|||
|
|
case TransactionStatus.Committed:
|
|||
|
|
case TransactionStatus.RolledBack:
|
|||
|
|
return result;
|
|||
|
|
|
|||
|
|
case TransactionStatus.Error:
|
|||
|
|
tr.RollBack();
|
|||
|
|
return result;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static TResult InvokeGroup<TResult>(this Document doc, Func<TransactionGroup, TResult> func, string name = "default")
|
|||
|
|
{
|
|||
|
|
using var tg = new TransactionGroup(doc, name);
|
|||
|
|
tg.Start();
|
|||
|
|
|
|||
|
|
var result = func(tg);
|
|||
|
|
|
|||
|
|
var status = tg.GetStatus();
|
|||
|
|
switch (status)
|
|||
|
|
{
|
|||
|
|
case TransactionStatus.Started:
|
|||
|
|
tg.Assimilate();
|
|||
|
|
//tr.Commit();
|
|||
|
|
return result;
|
|||
|
|
|
|||
|
|
case TransactionStatus.Committed:
|
|||
|
|
case TransactionStatus.RolledBack:
|
|||
|
|
return result;
|
|||
|
|
|
|||
|
|
case TransactionStatus.Error:
|
|||
|
|
tg.RollBack();
|
|||
|
|
return result;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static TResult InvokeSub<TResult>(this Document doc, Func<SubTransaction, TResult> func)
|
|||
|
|
{
|
|||
|
|
using var st = new SubTransaction(doc);
|
|||
|
|
st.Start();
|
|||
|
|
|
|||
|
|
var result = func(st);
|
|||
|
|
|
|||
|
|
var status = st.GetStatus();
|
|||
|
|
switch (status)
|
|||
|
|
{
|
|||
|
|
case TransactionStatus.Started:
|
|||
|
|
st.Commit();
|
|||
|
|
return result;
|
|||
|
|
|
|||
|
|
case TransactionStatus.Committed:
|
|||
|
|
case TransactionStatus.RolledBack:
|
|||
|
|
return result;
|
|||
|
|
|
|||
|
|
case TransactionStatus.Error:
|
|||
|
|
st.RollBack();
|
|||
|
|
return result;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//private static void UsingThisClass(doc doc)
|
|||
|
|
//{
|
|||
|
|
// //无返回值
|
|||
|
|
// doc.Invoke(m => { }, "x");
|
|||
|
|
// //有返回值
|
|||
|
|
// doc.Invoke<Level>(m =>
|
|||
|
|
// {
|
|||
|
|
// return Level.Create(doc, 5);
|
|||
|
|
// }, "x");
|
|||
|
|
|
|||
|
|
// doc.InvokeGroup(m => { doc.Invoke(mn => { }, "x"); }, "x");
|
|||
|
|
// doc.InvokeGroup<Level>(m => { doc.Invoke(mn => { }, "x"); doc.Invoke(mn => { }, "Y"); return Level.Create(doc, 5); }, "x");
|
|||
|
|
// doc.InvokeSub(m => { });
|
|||
|
|
// doc.InvokeSub<Level>(m => { return Level.Create(doc, 5); });
|
|||
|
|
//}
|
|||
|
|
|
|||
|
|
public static void Invoke(this Document doc, Action<Transaction> action, string name = "default")
|
|||
|
|
{
|
|||
|
|
using var tr = new Transaction(doc, name);
|
|||
|
|
tr.Start();
|
|||
|
|
|
|||
|
|
action(tr);
|
|||
|
|
|
|||
|
|
var status = tr.GetStatus();
|
|||
|
|
|
|||
|
|
switch (status)
|
|||
|
|
{
|
|||
|
|
case TransactionStatus.Started:
|
|||
|
|
tr.Commit();
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
case TransactionStatus.Committed:
|
|||
|
|
case TransactionStatus.RolledBack:
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
case TransactionStatus.Error:
|
|||
|
|
tr.RollBack();
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static void InvokeGroup(this Document doc, Action<TransactionGroup> action, string name = "default")
|
|||
|
|
{
|
|||
|
|
using var tg = new TransactionGroup(doc, name);
|
|||
|
|
tg.Start();
|
|||
|
|
|
|||
|
|
action(tg);
|
|||
|
|
|
|||
|
|
var status = tg.GetStatus();
|
|||
|
|
switch (status)
|
|||
|
|
{
|
|||
|
|
case TransactionStatus.Started:
|
|||
|
|
//tr.Commit();
|
|||
|
|
tg.Assimilate();
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
case TransactionStatus.Committed:
|
|||
|
|
case TransactionStatus.RolledBack:
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case TransactionStatus.Error:
|
|||
|
|
tg.RollBack();
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static void InvokeSub(this Document doc, Action<SubTransaction> action)
|
|||
|
|
{
|
|||
|
|
using var st = new SubTransaction(doc);
|
|||
|
|
st.Start();
|
|||
|
|
|
|||
|
|
action(st);
|
|||
|
|
|
|||
|
|
var status = st.GetStatus();
|
|||
|
|
switch (status)
|
|||
|
|
{
|
|||
|
|
case TransactionStatus.Started:
|
|||
|
|
st.Commit();
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
case TransactionStatus.Committed:
|
|||
|
|
case TransactionStatus.RolledBack:
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case TransactionStatus.Error:
|
|||
|
|
st.RollBack();
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|