Jason Jackson
Jason Jackson

Reputation: 17260

Retrieving properties of AutoCAD object in C#

I am attempting to interrogate AutoCAD objects from C#. I am interested in being able to grab all of the properties of a given object and output them. For example, in the below snippit of code I am looping through all of the items on screen and just reflecting against their first-class properties. The objects I care about often have a first-class AcadObject property which seems to hold the data I am after. The problem is that this is a __ComObject and that many of its nested propetry objects do no provide properties via reflection. For example, obj.AcadObject.Connectors appears to be a collection of connector objects, which I am very interested in. I can reflect to that depth using the debugger, but from there on in I am left guessing at properties of the Connectors collection and its objects (the .Net debugger does show a Count property which tipped me off). Using C#'s dynamic keyword and the DLR/COM binders built into .Net 4 I can probe these objects. For example, I can use a dynamic expression to grab obj.AcadObject.Connectors[0].Name, guessing that it had a name attribute. I am willing to use dynamic expressions to grab these properties but I need to know what the properties are in the first place. I have researched quite a bit and seem to be missing a reference to what these objects look like. There are a few other objects hanging off of AcadObject as well that I would like to export.

var currentDocument = Application.DocumentManager.MdiActiveDocument;
var editor = currentDocument.Editor;
var database = editor.Document.Database;

var result = editor.SelectAll();

using (var transaction = database.TransactionManager.StartTransaction())
{
    foreach (var id in result.Value.GetObjectIds())
    {

        var obj = transaction.GetObject(id, OpenMode.ForRead);

        var properties = TypeDescriptor.GetProperties(obj.AcadObject).Cast<PropertyDescriptor>().OrderBy(prop => prop.Name);


        writer.WriteLine("{0} ID:{1}", obj.GetType().Name, obj.Id);
        writer.WriteLine("\r\n\r\n");

        foreach (var property in properties)
        {
            var propertyObject = property.GetValue(obj.AcadObject);
            writer.WriteLine("  {0} = {1}", property.Name, propertyObject);
        }

        writer.Write("\r\n\r\n\r\n");
    }
}

Upvotes: 4

Views: 6484

Answers (4)

Maxence
Maxence

Reputation: 13286

You can try this utility to get more informations on your COM objects: http://www.codeproject.com/Articles/523417/Reflection-with-IDispatch-based-COM-objects

Upvotes: 0

RenderMan
RenderMan

Reputation: 11

You may find the MgdDbg utility to be of particular use when exploring a given drawing's Database... Depending on what you're after, and your version of AutoCAD, as Events, etc. are hard-coded rather than dynamic as Tony states here.

Upvotes: 1

Andrey Bushman
Andrey Bushman

Reputation: 12476

If you want to get ALL items from Database, then use it:

// Get all items from drawing Database. All ObjectIds will grouped by types;
Database db = Application.DocumentManager.MdiActiveDocument.Database;           
Dictionary<string, List<ObjectId>> dict = new Dictionary<string, List<ObjectId>>();
using (Transaction t = db.TransactionManager.StartTransaction()) {
    for (long i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++) {
        ObjectId id = ObjectId.Null;
        Handle h = new Handle(i);
        if (db.TryGetObjectId(h, out id)) {
            string type = id.ObjectClass.Name;
            if (!dict.Keys.Contains(type))
                dict.Add(type, new List<ObjectId>());
            dict[type].Add(id);
        }
    }
    t.Commit();
}

Regards

Upvotes: 2

Jason Jackson
Jason Jackson

Reputation: 17260

This isn't a perfect answer but I am going to put it here so it might help someone else. Using the immediate window I cast the obj.Acad to a dynamic, and then referenced down to the object in question such Connectors[0]. At that point I recast that to an object and was able to inspect it with a watch. Example code as it would run in the immediate window with a debug break after the obj set:

dynamic acad = obj.AcadObject;
object connector0 = (object)acad.Connectors[0];

The best I can figure is the the COM binder for the DLR is marshaling stuff over for me, and then once I get it cast back .Net debugger can figure out the properties. I am working on getting this discovery working with reflection...

Upvotes: 0

Related Questions