Author Topic: Creating Dictionary<AcRtm.RXClass, Type>  (Read 7827 times)

0 Members and 1 Guest are viewing this topic.

kaefer

  • Guest
Re: Creating Dictionary<AcRtm.RXClass, Type>
« Reply #15 on: August 22, 2012, 12:07:41 PM »
In AutoCAD 2013, RXClass has a new method that returns the managed wrapper type.

Even in 2013 there's one RXClass which doesn't allow calling GetRuntimeType on it: AcRxObject. It seems to bomb in a nested call to native_GetFactoryBase(AcRxClass* ).

@Andrey: If you still insist on doing something seemingly dangerous, what would happen when you skip the known troublemakers, that would be AcDbAnnotationScaleCollection and AcDbAnnotationScaleCollectionIterator?

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Creating Dictionary<AcRtm.RXClass, Type>
« Reply #16 on: August 22, 2012, 12:33:06 PM »
@Andrey: If you still insist on doing something seemingly dangerous, what would happen when you skip the known troublemakers, that would be AcDbAnnotationScaleCollection and AcDbAnnotationScaleCollectionIterator?
I do not know. I wanted to avoid exception processing ("try/catch" code block). I Hoped, that it's problem has a solution. I still not use it code in the my applications. I write Extended AutoCAD .Net API Libraries, which I will to use in my applications, and it code must was be there.

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Creating Dictionary<AcRtm.RXClass, Type>
« Reply #17 on: August 22, 2012, 01:01:47 PM »
In AutoCAD 2013, RXClass has a new method that returns the managed wrapper type.

Even in 2013 there's one RXClass which doesn't allow calling GetRuntimeType on it: AcRxObject. It seems to bomb in a nested call to native_GetFactoryBase(AcRxClass* ).

@Andrey: If you still insist on doing something seemingly dangerous, what would happen when you skip the known troublemakers, that would be AcDbAnnotationScaleCollection and AcDbAnnotationScaleCollectionIterator?

As kaefer mentioned skipping the troublemakers
 
Using RXClass.Create()
Two methods that created attached .txt files and only differ by filter and file name
Code - C#: [Select]
  1.        [CommandMethod("RxclassTypesDbo")]
  2.         public void RxclassTypesDbo()
  3.         {
  4.             Document doc = Application.DocumentManager.MdiActiveDocument;
  5.             Database db = doc.Database;
  6.             Editor ed = doc.Editor;
  7.             Dictionary<RXClass, Type> dic = new Dictionary<RXClass, Type>();
  8.                 RXClass rxEntity = RXClass.GetClass(typeof(DBObject));
  9.                 foreach (DictionaryEntry e in SystemObjects.ClassDictionary)
  10.                 {
  11.                     RXClass rxclass = e.Value as RXClass;
  12.                     if (rxclass.IsDerivedFrom(rxEntity))
  13.                     {
  14.                         RXObject rxo = rxclass.Create();
  15.                         if (rxo != null)
  16.                         {
  17.                             dic.Add(rxclass, rxo.GetType());
  18.                         }
  19.  
  20.                     }
  21.                 }
  22.                 using (StreamWriter tw = new StreamWriter(@"C:\Testing\rxDbotypes.txt"))
  23.                 {
  24.                     foreach (var de in dic)
  25.                     {
  26.                         tw.WriteLine("{0,-45:D} -------- {1,-45:D}", de.Key.Name, de.Value.Name);
  27.                     }
  28.                 }
  29.        
  30.         }
  31.  
  32.         [CommandMethod("RxclassTypesEnt")]
  33.         public void RxclassTypesEnt()
  34.         {
  35.             Document doc = Application.DocumentManager.MdiActiveDocument;
  36.             Database db = doc.Database;
  37.             Editor ed = doc.Editor;
  38.             Dictionary<RXClass, Type> dic = new Dictionary<RXClass, Type>();
  39.             RXClass rxEntity = RXClass.GetClass(typeof(Entity));
  40.             foreach (DictionaryEntry e in SystemObjects.ClassDictionary)
  41.             {
  42.                 RXClass rxclass = e.Value as RXClass;
  43.                 if (rxclass.IsDerivedFrom(rxEntity))
  44.                 {
  45.                     RXObject rxo = rxclass.Create();
  46.                     if (rxo != null)
  47.                     {
  48.                         dic.Add(rxclass, rxo.GetType());
  49.                     }
  50.                    
  51.                    
  52.                 }
  53.             }
  54.             using (StreamWriter tw = new StreamWriter(@"C:\Testing\rxEnttypes.txt"))
  55.             {
  56.                 foreach (var de in dic)
  57.                 {
  58.                     tw.WriteLine("{0,-45:D} -------- {1,-45:D}", de.Key.Name, de.Value.Name);
  59.                 }
  60.             }
  61.         }
  62.  

Results are very Impish
Quote

 AbsToolsDbFabrication                         -------- ImpCurve                                     
AbsToolsDbHanger                              -------- ImpCurve                                     
AcAecCamera                                   -------- ImpEntity                                   
AcDb2dPolyline                                -------- Polyline2d                                   
AcDb2dVertex                                  -------- Vertex2d                                     
AcDb2LineAngularDimension                     -------- LineAngularDimension2                       
AcDb3dPolyline                                -------- Polyline3d                                   
AcDb3dPolylineVertex                          -------- PolylineVertex3d                             
AcDb3dSolid                                   -------- Solid3d                                     
AcDb3PointAngularDimension                    -------- Point3AngularDimension               
...........       

rxDbotypes.txt created from DBObject filter
rxEnttypes.txt created from Entity filter
 
 

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Creating Dictionary<AcRtm.RXClass, Type>
« Reply #18 on: August 23, 2012, 09:31:08 AM »
I rewrote my code and supplied this with detailed comments. In the same place, in comments, I specified the questions. Respond me on them, please.
Code - C#: [Select]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Collections;
  6. using acad = Autodesk.AutoCAD.ApplicationServices.Application;
  7. using AcApp = Autodesk.AutoCAD.ApplicationServices;
  8. using AcDb = Autodesk.AutoCAD.DatabaseServices;
  9. using AcEd = Autodesk.AutoCAD.EditorInput;
  10. using AcRtm = Autodesk.AutoCAD.Runtime;
  11.  
  12. [assembly: AcRtm.CommandClass(typeof(Testing.Class1))]
  13.  
  14. namespace Testing {
  15.  
  16.         public class Class1 {
  17.  
  18.                 //In this method code I try to create dictionary, which for every RXClass contains according it wrapper type.
  19.                 //
  20.                 //The error occurs after a while after cmd was finished:
  21.                 //FATAL ERROR:  Unhandled Access Violation Reading 0x0008 Exception at 63972160h
  22.                 //
  23.                 //QUESTION: Why I get it error?
  24.                 [AcRtm.CommandMethod("cmd")]
  25.                 public void Cmd() {
  26.                         AcApp.Document doc = acad.DocumentManager.MdiActiveDocument;
  27.                         AcDb.Database db = doc.Database;
  28.                         AcEd.Editor ed = doc.Editor;
  29.  
  30.                         //target dictionary
  31.                         Dictionary<AcRtm.RXClass, Type> mngTypeDict = new Dictionary<AcRtm.RXClass, Type>();
  32.  
  33.                         //errors log
  34.                         StringBuilder sb = new StringBuilder();
  35.  
  36.                         //It is necessary to exclude some types from processing, differently we will receive the errors:
  37.                         //Error message:
  38.                         //INTERNAL ERROR:  !dbAnnotationScaleCollectioni.cpp@546: eNullEntityPointer
  39.                         //or
  40.                         //INTERNAL ERROR:  !dbAnnotationScaleCollectioni.cpp@37: eNullObjectPointer
  41.                         //
  42.                         //QUESTION: Why I get it errors?
  43.                         String[] types = new String[] { "AcDbAnnotationScaleCollection", "AcDbAnnotationScaleCollectionIterator" };
  44.  
  45.                         foreach (DictionaryEntry item in AcRtm.SystemObjects.ClassDictionary) {
  46.                                 AcRtm.RXClass rxClass = null;
  47.                                 Type type = null;
  48.                                 try {
  49.                                         if (item.Value != null) {
  50.                                                 rxClass = (AcRtm.RXClass)item.Value;
  51.                                                 if (!types.Contains(rxClass.Name)) {
  52.                                                         //I use such code:
  53.                                                         AcRtm.RXObject rxObj = rxClass.Create();
  54.                                                         type = rxObj.GetType();
  55.  
  56.                                                         //But I can't use such code, because AutoCAD right there will finish the operation without the error message:
  57.                                                         //using (AcRtm.RXObject rxObj = rxClass.Create()) {
  58.                                                         //    type = rxObj.GetType();
  59.                                                         //}
  60.                                                         //
  61.                                                         //QUESTION: Why I get it error?
  62.                                                 }
  63.                                         }
  64.                                         else {
  65.                                                 sb.AppendLine(String.Format("{0} key value is null.", item.Key));
  66.                                         }
  67.                                 }
  68.                                 catch (Exception ex) {
  69.                                         if (rxClass != null)
  70.                                                 sb.AppendLine(String.Format("Can't to create instance of {0}. Error: {1}", rxClass.Name, ex.Message));
  71.                                 }
  72.                         }
  73.                 }
  74.  
  75.                 //I try to find instances of "AcDbAnnotationScaleCollection" or "AcDbAnnotationScaleCollectionIterator"
  76.                 //
  77.                 //QUESTION: Why I can't find it?
  78.                 [AcRtm.CommandMethod("cmd2")]
  79.                 public void Cmd2() {
  80.                         AcApp.Document doc = acad.DocumentManager.MdiActiveDocument;
  81.                         AcDb.Database db = doc.Database;
  82.                         AcEd.Editor ed = doc.Editor;
  83.                         //I use such array, like in Cmd method:
  84.                         String[] types = new String[] { "AcDbAnnotationScaleCollection", "AcDbAnnotationScaleCollectionIterator" };
  85.  
  86.                         using (AcDb.Transaction tr = db.TransactionManager.StartTransaction()) {
  87.                                 //I execute iteration on all database objects:
  88.                                 for (long i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++) {
  89.                                         AcDb.ObjectId id = AcDb.ObjectId.Null;
  90.                                         AcDb.DBObject dbObj = null;
  91.                                         Type type = null;
  92.                                         AcDb.Handle h = new AcDb.Handle(i);
  93.                                         bool result = db.TryGetObjectId(h, out id);
  94.  
  95.                                         //But I can't find instances of "AcDbAnnotationScaleCollection" or "AcDbAnnotationScaleCollectionIterator":
  96.                                         //the condition is never executed.
  97.                                         if (result && id.IsValid && !id.IsNull && types.Contains(id.ObjectClass.Name)) {
  98.                                                 dbObj = tr.GetObject(id, AcDb.OpenMode.ForRead);
  99.                                                 type = dbObj.GetType();
  100.                                         }
  101.                                 }
  102.                                 tr.Abort();
  103.                         }
  104.                 }
  105.         }
  106. }
  107.  
« Last Edit: August 23, 2012, 09:53:14 AM by Andrey »

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Creating Dictionary<AcRtm.RXClass, Type>
« Reply #19 on: August 23, 2012, 09:47:43 AM »
rxDbotypes.txt created from DBObject filter
rxEnttypes.txt created from Entity filter
Yes, this is an interesting decision, thanks. But if there is a filter, then it means, what are eliminated some types and consequently we receive not complete result.
« Last Edit: August 23, 2012, 09:51:47 AM by Andrey »