Author Topic: Quick and Easy Managed Wrapper Type discovery Version 2  (Read 1542 times)

0 Members and 1 Guest are viewing this topic.

TheMaster

  • Guest
Quick and Easy Managed Wrapper Type discovery Version 2
« on: April 10, 2013, 12:59:18 PM »
Regarding: http://www.theswamp.org/index.php?topic=41371.0

Here's my latest experiment with filtering
ObjectIds based on their ObjectClass.

If anyone wants to compare the performance
of this and various other approaches, by all
means do.

Code - C#: [Select]
  1.  
  2. /// Excerpts from AcDbLinq.cs  Copyright (c)  2008-2013 Tony Tanzillo
  3.  
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8. using Autodesk.AutoCAD.Runtime;
  9. using Autodesk.AutoCAD.Internal;
  10. using System.Collections;
  11.  
  12. namespace Autodesk.AutoCAD.DatabaseServices
  13. {
  14.    public static class AcDbLinqExtensions
  15.    {
  16.  
  17.  
  18.       public static IEnumerable<T> GetObjects<T>(
  19.           this IEnumerable<ObjectId> ids,
  20.           OpenMode mode = OpenMode.ForRead,
  21.           bool openErased = false,
  22.           bool forceOpenOnLockedLayers = false ) where T : DBObject
  23.       {
  24.          if( ids.Any() )
  25.          {
  26.             TransactionManager tm = ids.First().Database.TransactionManager;
  27.  
  28.             RXClass rxclass = RXClass.GetClass( typeof( T ) );
  29.            
  30.             /// Call IsDerivedFrom() on each id's ObjectClass only
  31.             /// once, and cache the result:
  32.            
  33.             Cache<RXClass, bool> cache =
  34.                new Cache<RXClass, bool>(
  35.                   objclass => objclass.IsDerivedFrom( rxclass )
  36.                );
  37.  
  38.             if( typeof( T ) == typeof( DBObject ) )
  39.             {
  40.                foreach( ObjectId id in ids )
  41.                {
  42.                   yield return (T) tm.GetObject( id, mode, openErased,
  43.                      forceOpenOnLockedLayers );
  44.                }
  45.             }
  46.  
  47.             /// Use the cache if the RXClass has children:
  48.             else if( rxclass.GetHasChildren() )
  49.             {
  50.                foreach( ObjectId id in ids )
  51.                {
  52.                   if( cache[id.ObjectClass] )  
  53.                      yield return (T) tm.GetObject( id, mode, openErased,
  54.                         forceOpenOnLockedLayers );
  55.                }
  56.             }
  57.             else
  58.             {
  59.                foreach( ObjectId id in ids )
  60.                {
  61.                   if( id.ObjectClass == rxclass )
  62.                      yield return (T) tm.GetObject( id, mode, openErased,
  63.                         forceOpenOnLockedLayers );
  64.                }
  65.             }
  66.          }
  67.       }
  68.  
  69.       // Returns true if at least one RXClass is derived from
  70.       // the given RXClass:
  71.  
  72.       public static bool GetHasChildren( this RXClass rxclass )
  73.       {
  74.          foreach( DictionaryEntry e in SystemObjects.ClassDictionary )
  75.          {
  76.             if( rxclass == ( (RXClass) e.Value ).MyParent )
  77.                return true;
  78.          }
  79.          return false;
  80.       }
  81.  
  82.    }
  83.  
  84.    /// Essentially, a Dictionary<TKey, TValue> that implicitly
  85.    /// produces values for keys, using a delegate.
  86.    
  87.    public class Cache<TKey, TValue> : CacheBase<TKey, TValue>
  88.    {
  89.       Func<TKey, TValue> getValue = null;
  90.      
  91.       public Cache( Func<TKey, TValue> getvalue )
  92.       {
  93.          if( getvalue == null )
  94.             throw new ArgumentNullException("getvalue");
  95.          this.getValue = getvalue;
  96.       }
  97.  
  98.       protected override TValue GetValueForKey( TKey key )
  99.       {
  100.          return getValue( key );
  101.       }
  102.    }
  103.  
  104.    public abstract class CacheBase<TKey, TValue>
  105.    {
  106.       Dictionary<TKey, TValue> items = new Dictionary<TKey, TValue>();
  107.  
  108.       public CacheBase()
  109.       {
  110.       }
  111.  
  112.       public void Clear()
  113.       {
  114.          items.Clear();
  115.       }
  116.  
  117.       public bool Contains( TKey key )
  118.       {
  119.          return items.ContainsKey( key );
  120.       }
  121.  
  122.       public int Count
  123.       {
  124.          get
  125.          {
  126.             return items.Count;
  127.          }
  128.       }
  129.  
  130.       public TValue this[TKey key]
  131.       {
  132.          get
  133.          {
  134.             TValue result = default( TValue );
  135.             if( ! items.TryGetValue( key, out result ) )
  136.                result = items[key] = GetValueForKey( key );
  137.             return result;
  138.          }
  139.       }
  140.  
  141.       // Must throw an exception if a value cannot
  142.       // be produced for the given key:
  143.      
  144.       protected abstract TValue GetValueForKey( TKey key );
  145.    }
  146.    
  147. }
  148.  
  149.