public static class AcDbExtensionMethods
{
// This is a modified verison of the well-known GetObjects<T>() LINQ
// extension methods that have appeared in various threads here, by
// multiple authors.
// This code also includes other optimizations related to comparing
// the RXClasses of objectids for equivalence (this optimization has
// been prototyped and discussed on other threads here).
//
// The optimization presented here shows how to avoid calling
// ObjectId.GetObject() from a method that receives only a sequence
// of ObjectIds, without any database-resident container. To get
// the TransactionManager, we use the first ObjectId in the sequence.
// Note that this method presumes that all elements in the source
// sequence are from the same database, and makes no attempt to check
// for that.
public static IEnumerable<T> GetObjects<T>(
this IEnumerable<ObjectId> ids,
OpenMode mode = OpenMode.ForRead,
bool openErased = false,
bool forceOpenOnLockedLayers = false ) where T: DBObject
{
// If the source sequence is empty, do nothing
if( ids.Any() )
{
// Get the transaction manager from the first element in the sequence:
TransactionManager tm = ids.First().Database.TransactionManager;
// The rest is typical, with the exception that we call the
// TransactionManager's GetObject() method rather than the
// ObjectId's GetObject() method:
RXClass rxclass
= RXClass
.GetClass( typeof( T
) ); {
foreach( ObjectId id in ids )
{
yield return (T) tm.GetObject( id, mode, openErased, forceOpenOnLockedLayers );
}
}
// If at least one RXClass is derived from the runtime
// class for the generic argument type, then we need to
// call IsDerivedFrom() and the managed-to-native thunk.
// Otherwise, we can avoid calling IsDerivedFrom() and
// instead just compare each ObjectId's ObjectClass to
// the target RXClass:
else if( rxclass.GetHasChildren() )
{
foreach( ObjectId id in ids )
{
if( id.ObjectClass.IsDerivedFrom( rxclass ) )
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;
}
}