Понятие ObjectId

Каждый содержащийся в базе данных объект связан с несколькими уникальными идентификаторами:

  • Entity handle;
  • ObjectId;
  • Instance pointer (указатель на объект);

Наиболее распространенным способом получения доступа к объекту является ObjectId. Идентификаторы на основе ObjectId также удобны, когда ваш проект использует одновременно .NET API и ActiveX (COM) API. В случае создания AutoLISP-функций предпочтительнее будет использовать Handle-идентификаторы.

Указатели (свойство UnmanagedObject) уместно применять только при вызове функций из ARX-API через механизм P/Invoke; Идентификаторы-handle сохраняются между сеансами AutoCAD для каждого из чертежей, поэтому они являются лучшим способом доступа к объектам, если необходимо экспортировать информацию о чертеже во внешний файл, который впоследствии может быть использован для обновления чертежа. ObjectId объекта в базе данных существует только пока база данных загружена в память. После закрытия базы данных ObjectId, присвоенный объекту, перестаёт существует и может стать другим для данного объекта при следующем открытии базы данных.

Получение ObjectId

Перед тем как работать с каким-либо объектом необходимо получить его идентификатор ObjectId; он будет назначен существующему объекту в базе данных модели, при открытии файла чертежа. Новые объекты получают ObjectId после своего создания (при добавлении в модель AddEntityToDatabase). Есть 2 основных пути получения ObjectId для существующих объектов в БД чертежа:

  • Использовать соответствующие свойства у объектов БД чертежа: например, свойство Database.Clayer возвращает ObjectId активного слоя чертежа;

  • Использовать итеративный перебор таблицы символов, например, таблицы слоев Layer;

    Открытие объекта

    Как только ObjectId был получен, можно использовать функцию GetObject для открытия объекта из-под транзакции, связанного с данным ObjectId. Объект может быть открыт в одном из следующих режимов:

  • Read. Объект открыт для чтения;

  • Write. Объект открывается для записи (также для чтения), если он не был открыт ранее;

  • Notify. Объект открывается для информирования в случаях, когда объект закрыт или уже открыт для чтении или записи, но когда не был открыт для данного режима Notify. Этот режим предназначен для использования в тех случаях, когда объект может изменять себя из собственного кода, например при определении пользовательского объекта, который не поддерживается управляемым AutoCAD .NET API;

Следует открывать объект в том режиме, для которого нужен соответствующий доступ. Несмотря на удобство режима Write для чтения и записи, при его использовании затрачивается больше ресурсов на стороне нативного кода. Если вы не уверены, что открываемый объект : это тот, с которым вы хотите работать, откройте его сперва в режиме чтения, а затем переведите объект из режима чтения в режим записи. Дополнительные сведения об изменении способа открытия объекта см. в разделе. Обе функции GetObject и Open возвращают объект (подробнее о каждой см. раздел). При разработке на C# вам необходимо будет дополнительно приводить тип возвращаемого объекта к нужному классу с помощью модификатора as.

При работе с Dynamic Runtime Language (DLR) вам нет необходимости беспокоиться, открыт объект дли записи или для чтения. Открытие объекта происходит автоматически и незаметно для пользователя, как и процесс фиксации изменений, внесенных в объект, без использования транзакций. Подробнее см. статью. В следующих примерах показано, как получить запись LayerTableRecord для нулевого слоя текущей базы данных. В следующем примере транзакция удаляется вручную после того, как она больше не нужна.

Document acCurDb = Application.DocumentManager.MdiActiveDocument.Database;
Transaction acTrans = acCurDb.TransactionManager.StartTransaction();

LayerTableRecord acLyrTblRec;
acLyrTblRec = acTrans.GetObject(acCurDb.LayerZero,
                                OpenMode.ForRead) as LayerTableRecord;

acTrans.Dispose();

В следующем примере используется оператор using для утилизации транзакции после того, как она больше не нужна. Конструкция using является предпочтительной.

Document acCurDb = Application.DocumentManager.MdiActiveDocument.Database;
using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
    LayerTableRecord acLyrTblRec;
    acLyrTblRec = acTrans.GetObject(acCurDb.LayerZero,
                                    OpenMode.ForRead) as LayerTableRecord;
}