// Another Tony Tanzillo Classic
// http://www.theswamp.org/index.php?topic=42591.msg477887#msg477887
using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.AutoCAD.Runtime;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
using AcRx = Autodesk.AutoCAD.Runtime;
namespace Autodesk.AutoCAD.DatabaseServices
{
/// <summary> <c>Autodesk.AutoCAD.DatabaseServices</c> Extension methods mostly by Tony Tanzillo. </summary>
public static class AcDbExtensionMethods
{
private static readonly RXClass attDefClass
= RXObject
.GetClass(typeof (AttributeDefinition
));
/// <summary> Requires a transaction (not an OpenCloseTransaction) to be active when called:
/// <para>Returns an enumeration of all <c>AttributeReference</c>s attached to the <c>BlockReference</c></para>
/// plus all all <c>AttributeDefinition</c>s whose Constant property is true. </summary>
public static IEnumerable<DBText> GetAttributes(this BlockReference blockRef)
{
Transaction tr = blockRef.GetTransaction();
var btr = (BlockTableRecord)blockRef.DynamicBlockTableRecord.GetObject(OpenMode.ForRead);
if (btr.HasAttributeDefinitions)
{
foreach (ObjectId id in blockRef.AttributeCollection)
{
yield return (AttributeReference)tr.GetObject(id, OpenMode.ForRead);
}
foreach (ObjectId id in btr)
{
if (id.ObjectClass == attDefClass)
{
var attdef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead);
if (attdef.Constant)
yield return attdef;
}
}
}
}
// adapted from the above by CADbloke
/// <summary> Requires a transaction (not an OpenCloseTransaction) to be active when called:
/// <para>Gets all the <c>AttributeReference</c>s from a <c>BlockReference</c></para>
/// Does not get any Constant Attributes.</summary>
/// <param name="blockRef"> The BlockReference to get Attributes from. </param>
/// <returns> An enumerator that allows foreach to be used to process the attribute references in this collection. </returns>
public static IEnumerable<AttributeReference> GetAttributeReferences(this BlockReference blockRef)
{
Transaction tr = blockRef.GetTransaction();
var btr = (BlockTableRecord)blockRef.DynamicBlockTableRecord.GetObject(OpenMode.ForRead); // Dynamic?
if (btr.HasAttributeDefinitions)
{
foreach (ObjectId id in blockRef.AttributeCollection)
{
yield return (AttributeReference)tr.GetObject(id, OpenMode.ForRead);
}
}
}
// adapted from the above by CADbloke
/// <summary> Requires a transaction (not an OpenCloseTransaction) to be active when called:
/// <para>Gets all the <c>Constant</c> Attributes (<c>AttributeDefinition</c>s that are Constants) from a Block Reference. </para>
/// Does not get any <c>AttributeReference</c>s.</summary>
public static IEnumerable<AttributeDefinition> GetAttributeConstants(this BlockReference blockRef)
{
Transaction tr = blockRef.GetTransaction();
var btr = (BlockTableRecord)blockRef.DynamicBlockTableRecord.GetObject(OpenMode.ForRead); // Dynamic?
if (btr.HasAttributeDefinitions)
{
foreach (ObjectId id in btr)
{
if (id.ObjectClass == attDefClass)
{
var attdef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead);
if (attdef.Constant)
yield return attdef;
}
}
}
}
// adapted from the above by CADbloke
/// <summary> Requires a transaction (not an OpenCloseTransaction) to be active when called:
/// <para>Gets all of the <c>AttributeDefinition</c>s from a <c>BlockReference</c>.</para> </summary>
public static IEnumerable<AttributeDefinition> GetAttributeDefinitions(this BlockReference blockRef)
{
Transaction tr = blockRef.GetTransaction();
var btr = (BlockTableRecord)blockRef.DynamicBlockTableRecord.GetObject(OpenMode.ForRead);
if (btr.HasAttributeDefinitions)
{
foreach (ObjectId id in btr)
{
if (id.ObjectClass == attDefClass)
{
var attdef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead);
/*if (attdef.Constant)*/
{
yield return attdef;
}
}
}
}
}
/// <summary> Requires an active transaction (not an OpenCloseTransaction).
/// <para />Returns a dictionary whose values are either constant <c>AttributeDefinition</c>s
/// or <c>AttributeReference</c>s, keyed to their tags: </summary>
public static Dictionary<string, DBText> GetAttributesToDictionaryKeyByTag(this BlockReference blockref)
{
return blockref.GetAttributes().ToDictionary(a => GetTag(a), StringComparer.OrdinalIgnoreCase);
}
/// <summary> Gets the <c>Database.TransactionManager.TopTransaction</c>. </summary>
/// <exception cref="ArgumentNullException"> No database </exception>
/// <exception cref="Autodesk.AutoCAD.Runtime.Exception"> Requires an active transaction (NOT an OpenCloseTransaction) </exception>
public static Transaction GetTransaction(this DBObject obj)
{
if (obj.Database == null)
throw new ArgumentNullException
("obj",
"No Database");
Transaction tr = obj.Database.TransactionManager.TopTransaction;
if (tr == null)
throw new AcRx
.Exception(AcRx
.ErrorStatus.NoActiveTransactions);
return tr;
}
/// <summary> Gets the tag of an <c>AttributeDefinition</c> or <c>AttributeReference</c>. </summary>
/// <exception cref="ArgumentException"> requires an AttributeDefintion or AttributeReference. </exception>
/// <param name="dbtext"> <c>AttributeDefinition</c> or <c>AttributeReference</c> ONLY. </param>
/// <returns> The tag. </returns>
private static string GetTag(DBText dbtext)
{
var attdef = dbtext as AttributeDefinition;
if (attdef != null)
return attdef.Tag;
var attref = dbtext as AttributeReference;
if (attref != null)
return attref.Tag;
throw new ArgumentException
("requires an AttributeDefintion or AttributeReference"); }
}
}