I am new-ish to C# programming (and programming in general) but I'm getting my feet wet with AutoCAD development using the AutoDesk .NET API for projects at work.
There are certain repetitive tasks in AutoCAD dev that I've been creating helper methods for to simplify my code. In order to create an object(lines, polylines, annotation, etc...) in AutoCAD through the .API, the programmer has to write a fairly convoluted statement that accesses the AutoCAD environment, gets the current drawing, gets the database of the current drawing file, starts a transaction with the database, //do work
, then append the created entities to the database before finally committing and closing the transaction.
So I wrote the following code to simplify this task:
public static void CreateObjectActionWithinTransaction(Action<Transaction, Database, BlockTable, BlockTableRecord> action)
{
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;
action(transaction, database, blocktable, blockTableRecord);
transaction.Commit();
}
}
Then my Lambda expression that creates a generic MText
and sets up some parameters for it:
public static void createMtext(Point3d location, AttachmentPoint attachmentpoint, string contents, double height, short color, bool usebackgroundmask, bool usebackgroundcolor, double backgroundscale)
{
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);
});
}
And then finally, when I'm actually creating MText
somewhere, I can create it in one line, and pass in values for all the parameters without having to write out the huge transaction code for it:
Helpers.createMtext(insertpoint, AttachmentPoint.MiddleLeft, "hello world", .08, colors.AutoCAD_Red, true, true, 1.2);
So this is great and it works when I want to create an MText
by itself and put it somewhere. However, there are certain other situations where instead of just creating an MText
and placing it in the drawing, I want to create an MText
using the same basic premise as above, but return it as a value to be used somewhere else.
AutoCAD has annotation objects called Multileaders
which are essentially just an MText
just like above, but attached to some lines and an arrow to point at something in the drawing. In the API you need to define an MText
and attach it to the Multileader
object. However my above code can't be used because it doesn't return anything.
So my question boils down to, how can I create a method like above to create an object, but instead of just creating that object, have it return that object to be used by another piece of code?
Also are there any good resources for beginners on Lambda expressions? Books, websites, YouTube?