/// Excerpts from AcDbLinq.cs Copyright (c) 2008-2013 Tony Tanzillo
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Internal;
using System.Collections;
namespace Autodesk.AutoCAD.DatabaseServices
{
public static class AcDbLinqExtensions
{
public static IEnumerable<T> GetObjects<T>(
this IEnumerable<ObjectId> ids,
OpenMode mode = OpenMode.ForRead,
bool openErased = false,
bool forceOpenOnLockedLayers = false ) where T : DBObject
{
if( ids.Any() )
{
TransactionManager tm = ids.First().Database.TransactionManager;
RXClass rxclass
= RXClass
.GetClass( typeof( T
) );
/// Call IsDerivedFrom() on each id's ObjectClass only
/// once, and cache the result:
Cache<RXClass, bool> cache =
new Cache
<RXClass,
bool>( objclass => objclass.IsDerivedFrom( rxclass )
);
{
foreach( ObjectId id in ids )
{
yield return (T) tm.GetObject( id, mode, openErased,
forceOpenOnLockedLayers );
}
}
/// Use the cache if the RXClass has children:
else if( rxclass.GetHasChildren() )
{
foreach( ObjectId id in ids )
{
if( cache[id.ObjectClass] )
yield return (T) tm.GetObject( id, mode, openErased,
forceOpenOnLockedLayers );
}
}
else
{
foreach( ObjectId id in ids )
{
if( id.ObjectClass == rxclass )
yield return (T) tm.GetObject( id, mode, openErased,
forceOpenOnLockedLayers );
}
}
}
}
// Returns true if at least one RXClass is derived from
// the given RXClass:
public static bool GetHasChildren( this RXClass rxclass )
{
foreach( DictionaryEntry e in SystemObjects.ClassDictionary )
{
if( rxclass == ( (RXClass) e.Value ).MyParent )
return true;
}
return false;
}
}
/// Essentially, a Dictionary<TKey, TValue> that implicitly
/// produces values for keys, using a delegate.
public class Cache<TKey, TValue> : CacheBase<TKey, TValue>
{
Func<TKey, TValue> getValue = null;
public Cache( Func<TKey, TValue> getvalue )
{
if( getvalue == null )
throw new ArgumentNullException
("getvalue"); this.getValue = getvalue;
}
protected override TValue GetValueForKey( TKey key )
{
return getValue( key );
}
}
public abstract class CacheBase<TKey, TValue>
{
Dictionary
<TKey, TValue
> items
= new Dictionary
<TKey, TValue
>();
public CacheBase()
{
}
public void Clear()
{
items.Clear();
}
public bool Contains( TKey key )
{
return items.ContainsKey( key );
}
public int Count
{
get
{
return items.Count;
}
}
public TValue this[TKey key]
{
get
{
TValue result = default( TValue );
if( ! items.TryGetValue( key, out result ) )
result = items[key] = GetValueForKey( key );
return result;
}
}
// Must throw an exception if a value cannot
// be produced for the given key:
protected abstract TValue GetValueForKey( TKey key );
}
}