使用 .NET API 以正确的方式向模型添加元素 space

Adding elements to model space the correct way using .NET API

方法一

_AcDb.Line oLine = new _AcDb.Line(ptStart, ptEnd);
AddToModelSpace("PLOT", oLine);

其中 AddToModelSpace 是:

public static void AddToModelSpace(string strLayer, _AcDb.Entity oEntity)
{
    _AcAp.Document acDoc = _AcAp.Application.DocumentManager.MdiActiveDocument;
    _AcDb.Database acCurDb = acDoc.Database;
    _AcEd.Editor ed = acDoc.Editor;

    using (_AcDb.BlockTable bt = acCurDb.BlockTableId.GetObject(_AcDb.OpenMode.ForRead) as _AcDb.BlockTable)
    using (_AcDb.BlockTableRecord ms = bt[_AcDb.BlockTableRecord.ModelSpace].GetObject(_AcDb.OpenMode.ForWrite) as _AcDb.BlockTableRecord)
        ms.AppendEntity(oEntity);
    oEntity.Layer = strLayer;
    oEntity.Dispose();
}

方法二

// Get the current document and database
_AcAp.Document docActive = _AcAp.Application.DocumentManager.MdiActiveDocument;
_AcDb.Database docDB = docActive.Database;

// Start a transaction
using (_AcDb.Transaction acTrans = docDB.TransactionManager.StartTransaction())
{
    // Open the Block table for read
    _AcDb.BlockTable acBlkTbl;
    acBlkTbl = acTrans.GetObject(docDB.BlockTableId,
                                    _AcDb.OpenMode.ForRead) as _AcDb.BlockTable;

    // Open the Block table record Model space for write
    _AcDb.BlockTableRecord acBlkTblRec;
    acBlkTblRec = acTrans.GetObject(acBlkTbl[_AcDb.BlockTableRecord.ModelSpace],
                                    _AcDb.OpenMode.ForWrite) as _AcDb.BlockTableRecord;

    // Create line
    using (_AcDb.Line acLine = new _AcDb.Line(ptStart, ptEnd))
    {

        // Add the new object to the block table record and the transaction
        acBlkTblRec.AppendEntity(acLine);
        acTrans.AddNewlyCreatedDBObject(acLine, true);
    }

    // Save the new object to the database
    acTrans.Commit();
}

我在我的项目中使用了AddToModelSpace,希望它没问题!

方法二是Autodesk在开发者文档中推荐的方式(可以阅读this section)。

在方法一中,您使用ObjectId.GetObject() 方法打开BlockTable 和模型space 'BlockTableRecord'。此方法使用顶级事务打开对象,这意味着您应该使用一个活动事务来添加新创建的实体。您可以使用 Database.TransactionManager.TopTransaction 获取它。如果你根本不想使用事务,你必须使用 "for advanced use only" ObjectId.Open() 方法。

方法三应该使用一些从事务中调用的扩展方法。这是我使用的简化(非错误检查)摘录。

static class ExtensionMethods
{
    public static T GetObject<T>(
        this ObjectId id, 
        OpenMode mode = OpenMode.ForRead,
        bool openErased = false, 
        bool forceOpenOnLockedLayer = false)
        where T : DBObject
    {
        return (T)id.GetObject(mode, openErased, forceOpenOnLockedLayer);
    }

    public static BlockTableRecord GetModelSpace(this Database db, OpenMode mode = OpenMode.ForRead)
    {
        return SymbolUtilityServices.GetBlockModelSpaceId(db).GetObject<BlockTableRecord>(mode);
    }

    public static ObjectId Add (this BlockTableRecord owner, Entity entity)
    {
        var tr = owner.Database.TransactionManager.TopTransaction;
        var id = owner.AppendEntity(entity);
        tr.AddNewlyCreatedDBObject(entity, true);
        return id;
    }
}

使用示例:

using (var tr = db.TransactionManager.StartTransaction())
{
    var line = new Line(startPt, endPt) { Layer = layerName };
    db.GetModelSpace(OpenMode.ForWrite).Add(line);
    tr.Commit();
}