/// 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
{
/// <summary>
///
/// Returns an object that enumerates all references
/// to all blocks whose names match the given wildcard
/// pattern, open for read.
///
/// Requires an active transaction (NOT an OpenCloseTransaction)
///
/// </summary>
///
public static IEnumerable<BlockReference> GetBlockReferences(
this Database database,
string pattern )
{
if( string.IsNullOrWhiteSpace( pattern ) )
throw new ArgumentException
( "Requires a wildcard pattern" ); if( database == null )
throw new ArgumentNullException
( "database" ); Transaction tr = database.TransactionManager.TopTransaction;
if( tr == null )
throw new Autodesk
.AutoCAD.Runtime.Exception( ErrorStatus.NoActiveTransactions );
BlockTable blockTable = (BlockTable)
tr.GetObject( database.BlockTableId, OpenMode.ForRead );
return blockTable.Cast<ObjectId>()
.GetObjects<BlockTableRecord>()
.Where( btr => Utils.WcMatchEx( btr.Name, pattern, true ) )
.SelectMany( btr => btr.GetBlockReferences() );
}
/// <summary>
/// Gets an object that enumerates all references to the given
/// BlockTableRecord, including references to anonymous dynamic
/// BlockTableRecords, open for read.
/// </summary>
public static IEnumerable<BlockReference> GetBlockReferences(
this BlockTableRecord btr,
OpenMode mode = OpenMode.ForRead,
bool directOnly = true )
{
if( btr == null )
throw new ArgumentNullException
( "btr" ); var tr = btr.Database.TransactionManager.TopTransaction;
if( tr == null )
throw new InvalidOperationException
( "No transaction" ); var ids = btr.GetBlockReferenceIds( directOnly, true );
int cnt = ids.Count;
for( int i = 0; i < cnt; i++ )
{
yield return (BlockReference)
tr.GetObject( ids[i], mode, false, false );
}
if( btr.IsDynamicBlock )
{
BlockTableRecord btr2 = null;
var blockIds = btr.GetAnonymousBlockIds();
cnt = blockIds.Count;
for( int i = 0; i < cnt; i++ )
{
btr2 = (BlockTableRecord) tr.GetObject( blockIds[i],
OpenMode.ForRead, false, false );
ids = btr2.GetBlockReferenceIds( directOnly, true );
int cnt2 = ids.Count;
for( int j = 0; j < cnt2; j++ )
{
yield return (BlockReference)
tr.GetObject( ids[j], mode, false, false );
}
}
}
}
/// <summary>
/// The one, but not only GetObjects<T> (abridged), with due credits
/// to Jeff H, kaefer, Gile, et. al.
///
/// Returns an object that enumerates all instances of the
/// given generic argument type, opened accoring to the given
/// parameters.
/// </summary>
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
) ); {
foreach( ObjectId id in ids )
{
yield return (T) tm.GetObject( id, mode, openErased,
forceOpenOnLockedLayers );
}
}
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;
}
}
}