Reputation: 17260
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
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
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
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
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