3 回答

TA貢獻(xiàn)1818條經(jīng)驗(yàn) 獲得超7個贊
對于 AutoCAD 部分:
正如 Miiir 在評論中所說,不要返回對象,而是ObjectId
. 一個對象實(shí)例屬于一個事務(wù),因此如果您使用某個事務(wù)打開該對象,提交該事務(wù)并嘗試在另一個事務(wù)中使用該對象,AutoCAD 基本上只會崩潰。
使用 AutoCAD API始終遵循以下基本模式:
開始交易
創(chuàng)建新對象或使用事務(wù)來獲取現(xiàn)有對象。這可以通過使用
ObjectID
或 遍歷表并查找您感興趣的任何屬性(即BlockTable
、BlockTableRecord
、LayerTable
等)來完成。對對象做一些事情。
提交或中止事務(wù)。
如果您嘗試?yán)@過第 1 步和第 2 步,則效果不會很好。所以, return ObjectID
,然后使用 id 在另一個事務(wù)中獲取對象。
至于 C# 部分:
如果您希望使用委托返回值,那Action<T>
不是您的朋友。Action
不返回值,它只是“行動”,因此得名。如果您想使用委托返回一個值,您有 2 個選項(xiàng):
定義自定義委托類型。
使用 .NET 框架提供的通用委托
Func<T1,T2,T3,T4,TResult>
。
你應(yīng)該使用哪一個?在您的情況下,我可能會選擇選項(xiàng) 1,原因很簡單,因?yàn)槟拇a將更加簡潔且易于維護(hù)。我將在這個例子中使用它。使用Func
的工作方式完全相同,只是你的函數(shù)簽名看起來有點(diǎn)難看。
自定義委托:
//somewhere in your code inside a namespace (rather than a class)
public delegate ObjectId MyCreateDelegate(Transaction transaction, Database db,
BlockTable blockTable, BlockTableRecord blockTableRecord);
然后你的一般方法
public static ObjectId CreateObjectActionWithinTransaction(MyCreateDelegate createDel)
{
ObjectId ret;
var document = Application.DocumentManager.MdiActiveDocument;
var database = document.Database;
using (var transaction = document.TransactionManager.StartTransaction())
{
BlockTable blocktable = transaction.GetObject(database.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord blockTableRecord = transaction.GetObject(blocktable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
//here createMtext will get called in this case, and return ObjectID
ret = createDel(transaction, database, blocktable, blockTableRecord);
transaction.Commit();
}
return ret;
}
以及使用 lambda 的具體方法:
public ObjectId createMtext(Point3d location, AttachmentPoint attachmentpoint, string contents, double height, short color, bool usebackgroundmask, bool usebackgroundcolor, double backgroundscale)
{
//here you can return the result the general function
return CreateObjectActionWithinTransaction((transaction, database, blocktable, blocktablerecord) =>
{
MText mt = new MText();
mt.SetDatabaseDefaults();
mt.Location = location;
mt.Attachment = attachmentpoint;
mt.Contents = contents;
mt.Height = height;
mt.Color = Color.FromColorIndex(ColorMethod.ByAci, color);
mt.BackgroundFill = usebackgroundmask;
mt.UseBackgroundColor = usebackgroundcolor;
mt.BackgroundScaleFactor = backgroundscale;
blocktablerecord.AppendEntity(mt);
transaction.AddNewlyCreatedDBObject(mt, true);
//make sure to get ObjectId only AFTER adding to db.
return mt.ObjectId;
});
}
最后,像這樣使用它
ObjectId mtId = Helpers.createMtext(insertpoint, AttachmentPoint.MiddleLeft, "hello world", .08, colors.AutoCAD_Red, true, true, 1.2);
//now use another transaction to open the object and do stuff to it.

TA貢獻(xiàn)1827條經(jīng)驗(yàn) 獲得超8個贊
我寧愿使用從調(diào)用方法中的事務(wù)中調(diào)用的擴(kuò)展方法,而不是使用委托。
static class ExtensionMethods
{
public static BlockTableRecord GetModelSpace(this Database db, OpenMode mode = OpenMode.ForRead)
{
var tr = db.TransactionManager.TopTransaction;
if (tr == null)
throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NoActiveTransactions);
return (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), mode);
}
public static void Add(this BlockTableRecord btr, Entity entity)
{
var tr = btr.Database.TransactionManager.TopTransaction;
if (tr == null)
throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NoActiveTransactions);
btr.AppendEntity(entity);
tr.AddNewlyCreatedDBObject(entity, true);
}
public static MText AddMtext(this BlockTableRecord btr,
Point3d location,
AttachmentPoint attachmentpoint,
string contents,
double height,
short color = 256,
bool usebackgroundmask = false,
bool usebackgroundcolor = false,
double backgroundscale = 1.5)
{
MText mt = new MText();
mt.SetDatabaseDefaults();
mt.Location = location;
mt.Attachment = attachmentpoint;
mt.Contents = contents;
mt.Height = height;
mt.ColorIndex = color;
mt.BackgroundFill = usebackgroundmask;
mt.UseBackgroundColor = usebackgroundcolor;
mt.BackgroundScaleFactor = backgroundscale;
btr.Add(mt);
return mt;
}
}
使用示例:
public static void Test()
{
var doc = AcAp.DocumentManager.MdiActiveDocument;
var db = doc.Database;
using (var tr = db.TransactionManager.StartTransaction())
{
var ms = db.GetModelSpace(OpenMode.ForWrite);
var mt = ms.AddMtext(Point3d.Origin, AttachmentPoint.TopLeft, "foobar", 2.5);
// do what you want with 'mt'
tr.Commit();
}
}

TA貢獻(xiàn)2039條經(jīng)驗(yàn) 獲得超8個贊
我不熟悉 AutoCad API,但似乎“transaction.Commit()”是實(shí)際執(zhí)行將 MText 放置在模型上的操作的行。
如果是這種情況;我會做如下的事情:
public MText CreateMTextObject({parameters})
{
//code
Return textObject
}
public PlaceTextObject({parameters})
{
CreateTextObject(parameters).Commit()
}
這樣,您可以選擇保留文本對象以供進(jìn)一步操作,同時仍然允許選擇一次性應(yīng)用它。它也將只有一個用于制作對象的代碼塊,確保兩種方法的實(shí)現(xiàn)沒有差異
- 3 回答
- 0 關(guān)注
- 134 瀏覽
添加回答
舉報(bào)