Для детали AutoCAD:
Как сказал Мииир в комментарии, не возвращайте объект, а скорее ObjectId
.Экземпляр объекта принадлежит транзакции, поэтому если вы откроете объект с помощью какой-либо транзакции, зафиксируете транзакцию и попробуете использовать этот объект в другой транзакции, AutoCAD в основном просто рухнет.
Работа с AutoCAD API всегда следует этому базовому шаблону:
- Начать транзакцию
- Создать новый объект или использовать транзакцию для получения существующего объекта.Это достигается либо с помощью
ObjectID
, либо с помощью циклического перебора таблиц и поиска любых интересующих вас атрибутов (например, BlockTable
, BlockTableRecord
, LayerTable
и т. Д.) - объект.
- Подтверждение или отмена транзакции.
Если вы попытаетесь обойти шаги 1 и 2, это не сработает.Итак, верните ObjectID
, а затем используйте id для получения объекта в другой транзакции.
Что касается части C #:
Если вы хотите вернуть значение с помощью делегата,Action<T>
не твой друг.Action
не возвращает значение, оно только «действует», то есть имя.Если вы хотите использовать делегата для возврата значения, у вас есть 2 варианта:
Определить пользовательский тип делегата.
Использовать универсальный делегатпоставляется .NET Framework Func<T1,T2,T3,T4,TResult>
.
Какой из них вы должны использовать?В вашем случае я бы, вероятно, выбрал вариант 1 по той простой причине, что ваш код будет намного чище и проще в обслуживании.Я буду использовать это в этом примере.Использование Func
будет работать точно так же, за исключением того, что сигнатуры вашей функции будут выглядеть немного уродливо.
Пользовательский делегат:
//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;
}
и конкретный метод с лямбдой:
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.
Учебные ресурсы:
И, наконец, чтобы понять лямбдавыражений, вы должны начать с понимания делегатов, если вы этого еще не сделали.Все лямбды - это синтаксический сахар для создания экземпляра объекта делегата, который указывает либо на метод, либо на анонимный метод, как вы сделали в своем примере. Этот урок выглядит довольно хорошо.И помните, такие делегаты, как Action
, Func
и Predicate
, или ничем не отличаются.Поэтому, независимо от того, определяете ли вы свой собственный делегат или используете готовое решение, лямбда-выражения не имеют значения.
Для обзора лямбды обратитесь к этому руководству .
Не ограничивайте себя двумя источниками, которые я предоставил.Просто Google это, и лучшие 10 хитов будут довольно хорошей информацией.Вы также можете проверить Pluralsight .Я много учусь там.