Kerry 发表于 2010-1-27 03:05:23

. NET块例程

AutoCAD块的库线程
鼓励成员在中发布有关
AutoCAD块的任何函数、方法和片段。NET : C#、VB、F#、Python等
请随意添加注释、描述性注释、限制和图片来记录您的帖子。
请以常规主题发布问题。
**** Hidden Message *****

fixo 发表于 2010-1-28 07:15:10

下面是一个非常基本的例子,如何正确创建块,我希望

using System;
using System.Collections.Generic;
using System.Text;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.ApplicationServices;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
using Autodesk.AutoCAD.EditorInput;
.................................................
      public static ObjectId CreateLabelBlock(string blockname)
      {
            ObjectId blkid = ObjectId.Null;
            try
            {
                Database db = HostApplicationServices.WorkingDatabase;
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                  BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite, false);
                  if (bt.Has(blockname))
                  {
                        blkid = bt;
                  }
                  else
                  {
                        BlockTableRecord btr = new BlockTableRecord();
                        btr.Name = blockname;
                        btr.Explodable = true;
                        btr.Origin = new Point3d(0, 0, 0);
                        btr.Units = UnitsValue.Inches;
                        btr.BlockScaling = BlockScaling.Any;
                        Line line = new Line(new Point3d(-2, -0.4, 0), new Point3d(2, -0.4, 0));
                        line.Layer = "0";
                        line.ColorIndex = 14;
                        btr.AppendEntity(line);
                        line = new Line(new Point3d(-2, 0.4, 0), new Point3d(2, 0.4, 0));
                        line.Layer = "0";
                        line.ColorIndex = 14;
                        btr.AppendEntity(line);
                        line = new Line(new Point3d(2, -0.4, 0), new Point3d(2, 0.4, 0));
                        line.Layer = "0";
                        line.ColorIndex = 14;
                        btr.AppendEntity(line);
                        line = new Line(new Point3d(-2, -0.4, 0), new Point3d(-2, 0.4, 0));
                        line.Layer = "0";
                        line.ColorIndex = 14;
                        btr.AppendEntity(line);
                        AcadApp.SetSystemVariable("CECOLOR", "ByBlock");
                        
                        AttributeDefinition ad = new AttributeDefinition();
                        ad.Layer = "0";
                        //by default applied a current text style
                        ad.Tag = "DETAIL";
                        ad.TextString = "X-Ladder";
                        ad.Prompt = "Detail name";
                        ad.Position = new Point3d(0, 0, 0);
                        ad.HorizontalMode = TextHorizontalMode.TextMid;
                        ad.VerticalMode = TextVerticalMode.TextVerticalMid;
                        ad.AlignmentPoint = ad.Position;
                        btr.AppendEntity(ad);
                        blkid = bt.Add(btr);
                        AcadApp.SetSystemVariable("CECOLOR", "ByLayer");
                        tr.AddNewlyCreatedDBObject(btr, true);
                  }
                  tr.Commit();
                }
            }
            catch (Autodesk.AutoCAD.Runtime.Exception ex)
            {
                AcadApp.ShowAlertDialog("ERROR: " + "\n" + ex.Message + "\nSOURCE: " + ex.StackTrace);
            }
            return blkid;
      }

~'J'~

T.Willey 发表于 2010-1-28 10:59:26

这是一个用于在布局中按布局名称插入块的方法。我现在会稍微更改一下,但这是一个很好的例子。
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
public static ObjectId InsertBlock ( Database db, string loName, string blkName, Point3d insPt ) {
    ObjectId RtnObjId = ObjectId.Null;
    using ( Transaction Trans = db.TransactionManager.StartTransaction( ) ) {
      DBDictionary LoDict = Trans.GetObject( db.LayoutDictionaryId, OpenMode.ForRead ) as DBDictionary;
      foreach ( DictionaryEntry de in LoDict ) {
            if ( string.Compare( ( string )de.Key, loName, true ).Equals( 0 ) ) {
                Layout Lo = Trans.GetObject( ( ObjectId )de.Value, OpenMode.ForWrite ) as Layout;
                BlockTable BlkTbl = Trans.GetObject( db.BlockTableId, OpenMode.ForRead ) as BlockTable;
                BlockTableRecord LoRec = Trans.GetObject( Lo.BlockTableRecordId, OpenMode.ForRead ) as BlockTableRecord;
                ObjectId BlkTblRecId = GetNonErasedTableRecordId( BlkTbl.Id, blkName );
                if ( BlkTblRecId.IsNull ) {
                  string BlkPath = HostApplicationServices.Current.FindFile( blkName + ".dwg", db, FindFileHint.Default );
                  if ( string.IsNullOrEmpty( BlkPath ) )
                        return RtnObjId;
                  BlkTbl.UpgradeOpen( );
                  using ( Database tempDb = new Database( false, true ) ) {
                        tempDb.ReadDwgFile( BlkPath, FileShare.Read, true, null );
                        db.Insert( blkName, tempDb, false );
                  }
                  BlkTblRecId = GetNonErasedTableRecordId( BlkTbl.Id, blkName );
                }
                LoRec.UpgradeOpen( );
                BlockReference BlkRef = new BlockReference( insPt, BlkTblRecId );
                LoRec.AppendEntity( BlkRef );
                Trans.AddNewlyCreatedDBObject( BlkRef, true );
                BlockTableRecord BlkTblRec = Trans.GetObject( BlkTblRecId, OpenMode.ForRead ) as BlockTableRecord;
                if ( BlkTblRec.HasAttributeDefinitions ) {
                  foreach ( ObjectId objId in BlkTblRec ) {
                        AttributeDefinition AttDef = Trans.GetObject( objId, OpenMode.ForRead ) as AttributeDefinition;
                        if ( AttDef != null ) {
                            AttributeReference AttRef = new AttributeReference( );
                            AttRef.SetAttributeFromBlock( AttDef, BlkRef.BlockTransform );
                            BlkRef.AttributeCollection.AppendAttribute( AttRef );
                            Trans.AddNewlyCreatedDBObject( AttRef, true );
                        }
                  }
                }
                Trans.Commit( );
            }
      }
    }
    return RtnObjId;
}

谢谢Oleg。忘记添加Tony T.
public static ObjectId GetNonErasedTableRecordId( ObjectId TableId, string Name )
    // Posted by Tony Tanzillo 01Sept2006
{
   ObjectId id = ObjectId.Null;
   using( Transaction tr = TableId.Database.TransactionManager.StartTransaction() )
   {
      SymbolTable table = (SymbolTable) tr.GetObject( TableId, OpenMode.ForRead );
      if( table.Has( Name ) )
      {
         id = table;
         if( !id.IsErased )
            return id;
         foreach( ObjectId recId in table )
         {
            if( ! recId.IsErased )
            {
               SymbolTableRecord rec = (SymbolTableRecord) tr.GetObject( recId, OpenMode.ForRead );
               if( string.Compare( rec.Name, Name, true ) == 0 )
                  return recId;
            }
         }
      }
   }
   return id;
}

huiz 发表于 2010-8-15 09:45:16

此代码将现有块放置在 ModelSpace 中,添加属性并将其放置在正确的层上。如果块具有注释性,它还会管理当前注释比例。
感谢 fro2001 的这段伟大的代码!
' This procedure will insert a block into the current drawing. It also controls the defined attributes and it will
' add the current Annotation Scale if the block is Annotative.
' Code contribution:
' - fro2001 - via TheSwamp.org
Public Sub hzInsertBlockMSWithAttributes(ByVal pntInsert As Geometry.Point3d,
                                           ByVal strBlockName As String,
                                           ByVal dScale As Double,
                                           ByVal strLayerName As String,
                                           ByVal arrAttrValues As ArrayList)
    Dim db As Database = HostApplicationServices.WorkingDatabase
    Using tr As Transaction = db.TransactionManager.StartTransaction
      Dim bt As BlockTable = db.BlockTableId.GetObject(OpenMode.ForRead)
      Dim btrMS As BlockTableRecord = bt(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForRead)
      If Not bt.Has(strBlockName) Then
      Exit Sub
      Else
      btrMS.UpgradeOpen()
      End If
      Dim btr As BlockTableRecord = bt(strBlockName).GetObject(OpenMode.ForRead)
      Dim bref As New BlockReference(pntInsert, btr.ObjectId)
      btrMS.AppendEntity(bref)
      tr.AddNewlyCreatedDBObject(bref, True)
      ' set annotation scale if block is annotative
      If btr.Annotative = AnnotativeStates.True Then
      Dim ocm As ObjectContextManager = db.ObjectContextManager
      Dim occ As ObjectContextCollection = ocm.GetContextCollection("ACDB_ANNOTATIONSCALES")
      Internal.ObjectContexts.AddContext(bref, occ.CurrentContext)
      End If
      ' set attributes and values
      ' TODO: Set attribute to layer of block or layer of original definition, now it will be placed on layer 0
      ' TODO: Check if attribute is annotative, it is possible to create non-annotative blocks with annotative attributes
      Dim ccAttCounter As Integer = 0
      For Each objId As ObjectId In btr
      Dim ent As Entity = objId.GetObject(OpenMode.ForRead)
      If TypeOf ent Is AttributeDefinition Then
          ent.UpgradeOpen()
          Dim attDef As AttributeDefinition = CType(ent, AttributeDefinition)
          Dim attRef As New AttributeReference
          attRef.SetAttributeFromBlock(attDef, bref.BlockTransform)
          ' check if there is a value to add
          If arrAttrValues.Count - 1 >= ccAttCounter Then
            attRef.TextString = arrAttrValues(ccAttCounter).ToString.Trim
          Else
            attRef.TextString = ""
          End If
          bref.AttributeCollection.AppendAttribute(attRef)
          tr.AddNewlyCreatedDBObject(attRef, True)
          ccAttCounter += 1
      End If
      Next
      ' set layer
      ' TODO: Check if layername exist
      bref.Layer = strLayerName
      ' commit
      tr.Commit()
    End Using
End Sub

gile 发表于 2010-11-23 17:43:48

嗨,
试图帮助某人 http://www.acadnetwork.com/,谁想删除重复的块引用。
被视为重复块,具有相同的名称,图层,插入点,旋转和比例的块。
我首先使用“Duplicate”扩展方法编写了一个C#例程,我认为它是改进我非常新的F#学习的一个很好的练习。
下面是两种实现。
using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
namespace DuplicateTest
{
    public static class BlockRefExtension
    {
      public static bool Duplicate(this BlockReference blk1, BlockReference blk2)
      {
            Tolerance tol = new Tolerance(1e-6, 1e-6);
            return
                blk1.OwnerId == blk2.OwnerId &&
                blk1.Name == blk2.Name &&
                blk1.Layer == blk2.Layer &&
                Math.Round(blk1.Rotation, 5) == Math.Round(blk2.Rotation, 5) &&
                blk1.Position.IsEqualTo(blk2.Position, tol) &&
                blk1.ScaleFactors.IsEqualTo(blk2.ScaleFactors, tol);
      }
    }
    public class Commands
    {
      
      public void DelDupBlkRef()
      {
            try
            {
                int del = DeleteDuplicatedBlockRef();
                Application.ShowAlertDialog(del.ToString() + " duplicated block(s) have been erased");
            }
            catch (System.Exception e)
            {
                Application.ShowAlertDialog("\nError: " + e.Message);
            }
      }
      private int DeleteDuplicatedBlockRef()
      {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            int result = 0;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                foreach (ObjectId id in bt)
                {
                  BlockTableRecord btr =
                        (BlockTableRecord)tr.GetObject(id, OpenMode.ForWrite);
                  ObjectIdCollection idCol = btr.GetBlockReferenceIds(true, false);
                  for (int i = 0; iBlockTableRecord
            for oId in btr.GetBlockReferenceIds(true, false) do
                lstBlockReference :: lst
      lst
    let rec findDups acc blks =
      match blks with
      | [] -> acc
      | h :: t -> let pair = List.partition (fun x -> Duplicate x h) t
                  findDups (acc @ (fst pair)) (snd pair)
    let delBlk lst =
      List.iter (fun (x: BlockReference) -> x.Erase()) lst
      lst.Length
               
    let cnt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
            |> getRefs |> findDups [] |> delBlk
    tr.Commit()
    cnt
      
[]
let Test() =
    try
      let del = DeleteDuplicatedBlockRef()
      Application.ShowAlertDialog(del.ToString() + " duplicated block(s) have been erased")
    with
      |ex -> Application.ShowAlertDialog(ex.Message)

mohnston 发表于 2010-12-10 05:26:13

一个简单的小程序,它将改变基于动态块的所有块引用的Visibilty参数代码6]

gile 发表于 2011-2-25 14:05:39

这个函数将按名称获取所有动态块。
通常这是一个简单的过滤器,但动态块一旦更改动态属性就会变得匿名。
      public static ObjectIdCollection GetDynamicBlocksByName(string BlkName)
      {
            ObjectIdCollection res = new ObjectIdCollection();
            Database db = Application.DocumentManager.MdiActiveDocument.Database;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                //get the blockTable and iterate through all block Defs
                BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                foreach (ObjectId btrId in bt)
                {
                  //get the block Def and see if it is anonymous
                  BlockTableRecord btr = (BlockTableRecord)trans.GetObject(btrId, OpenMode.ForRead);
                  if (btr.IsDynamicBlock && btr.Name.Equals(BlkName))
                  {
                        //get all anonymous blocks from this dynamic block
                        ObjectIdCollection anonymousIds = btr.GetAnonymousBlockIds();
                        ObjectIdCollection dynBlockRefs = new ObjectIdCollection();
                        foreach (ObjectId anonymousBtrId in anonymousIds)
                        {
                            //get the anonymous block
                            BlockTableRecord anonymousBtr = (BlockTableRecord)trans.GetObject(anonymousBtrId, OpenMode.ForRead);
                            //and all references to this block
                            ObjectIdCollection blockRefIds = anonymousBtr.GetBlockReferenceIds(true, true);
                            foreach (ObjectId id in blockRefIds) dynBlockRefs.Add(id);
                        }
                        res = dynBlockRefs;
                        break;
                  }
                }
                trans.Commit();
            }
            return res;
      }

gile 发表于 2011-11-5 08:12:21

嗨,
这是属性提取的小例子。
我尝试使用Linq扩展方法和扩展类中定义的其他一些方法以“声明性”风格编写它(感谢Thorsten 'kaefer' @ TheSwamp的“邪恶”方法)。
提取收集在 System.Data.DataTable 中,以便可以轻松地将其转换为 AutoCAD 表、Exel 工作表等。
DataTable.WriteXls() 扩展方法在与 Excel 应用程序交互时使用后期绑定,以避免版本引用依赖关系。
BlockAttribute 类,它定义了一个新类型,其主要属性为:
- Block:块(有效)名称 ;
- 属性:块属性的字典,其中Key是标签,Value是文本字符串。
BlockAttributeEqualityComparer 类实现了 IEqualityComparer
接口,以便 BlockAttribute 集合可以与某些 Linq 扩展方法一起使用,如 GroupBy()。
using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace AttributeExtraction
{
    public class BlockAttribute
    {
      private string _name;
      private Dictionary _atts;
      // Public read only properties
      public string Name
      {
            get { return _name; }
      }
      public Dictionary Attributes
      {
            get { return _atts; }
      }
      public string this
      {
            get { return _atts; }
      }
      // Constructors
      public BlockAttribute(BlockReference br)
      {
            SetProperties(br);
      }
      public BlockAttribute(ObjectId id)
      {
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            using (Transaction tr = doc.TransactionManager.StartTransaction())
            {
                SetProperties(tr.GetObject(id, OpenMode.ForRead) as BlockReference);
            }
      }
      // Public method
      new public string ToString()
      {
            if (_atts != null && _atts.Count > 0)
                return string.Format("{0}: {1}",
                  _name,
                  _atts.Select(a => string.Format("{0}={1}", a.Key, a.Value))
                        .Aggregate((a, b) => string.Format("{0}; {1}", a, b)));
            return _name;
      }
      // Private method
      private void SetProperties(BlockReference br)
      {
            if (br == null) return;
            _name = br.GetEffectiveName();
            _atts = new Dictionary();
            br.AttributeCollection
                .GetObjects()
                .Iterate(att => _atts.Add(att.Tag.ToUpper(), att.TextString));
      }
    }
    public class BlockAttributeEqualityComparer : IEqualityComparer
    {
      public bool Equals(BlockAttribute x, BlockAttribute y)
      {
            return
                x.Name.Equals(y.Name, StringComparison.CurrentCultureIgnoreCase) &&
                x.Attributes.SequenceEqual(y.Attributes);
      }
      public int GetHashCode(BlockAttribute obj)
      {
            return base.GetHashCode();
      }
    }
}

扩展类提供了扩展方法,允许以更“声明性”的风格编写代码
,并提供从BlockAttribute集合构建DataTable并将此DataTable转换为xls,csv文件或AutoCAD表的方法。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using Autodesk.AutoCAD.DatabaseServices;
using AcDataTable = Autodesk.AutoCAD.DatabaseServices.DataTable;
namespace AttributeExtraction
{
    public static class Extensions
    {
      // Opens a DBObject in ForRead mode (kaefer @ TheSwamp)
      public static T GetObject(this ObjectId id) where T : DBObject
      {
            return id.GetObject(OpenMode.ForRead);
      }
      // Opens a DBObject in the given mode (kaefer @ TheSwamp)
      public static T GetObject(this ObjectId id, OpenMode mode) where T : DBObject
      {
            return id.GetObject(mode) as T;
      }

      // Opens a collection of DBObject in ForRead mode (kaefer @ TheSwamp)      
      public static IEnumerable GetObjects(this IEnumerable ids) where T : DBObject
      {
            return ids.GetObjects(OpenMode.ForRead);
      }
      // Opens a collection of DBObject in the given mode (kaefer @ TheSwamp)
      public static IEnumerable GetObjects(this IEnumerable ids, OpenMode mode) where T : DBObject
      {
            return ids
                .Cast()
                .Select(id => id.GetObject(mode))
                .Where(res => res != null);
      }
      // Applies the given Action to each element of the collection (mimics the F# Seq.iter function).
      public static void Iterate(this IEnumerable collection, Action action)
      {
            foreach (T item in collection) action(item);
      }
      // Applies the given Action to each element of the collection (mimics the F# Seq.iteri function).
      // The integer passed to the Action indicates the index of element.
      public static void Iterate(this IEnumerable collection, Action action)
      {
            int i = 0;
            foreach (T item in collection) action(item, i++);
      }
      // Gets the block effective name (anonymous dynamic blocs).
      public static string GetEffectiveName(this BlockReference br)
      {
            if (br.IsDynamicBlock)
                return br.DynamicBlockTableRecord.GetObject().Name;
            return br.Name;
      }
      // Creates a System.Data.DataTable from a BlockAttribute collection.
      public static System.Data.DataTable ToDataTable(this IEnumerable blockAtts, string name)
      {
            System.Data.DataTable dTable = new System.Data.DataTable(name);
            dTable.Columns.Add("Name", typeof(string));
            dTable.Columns.Add("Quantity", typeof(int));
            blockAtts
                .GroupBy(blk => blk, (blk, blks) => new { Block = blk, Count = blks.Count() }, new BlockAttributeEqualityComparer())
                .Iterate(row =>
                {
                  System.Data.DataRow dRow = dTable.Rows.Add(row.Block.Name, row.Count);
                  row.Block.Attributes.Iterate(att =>
                  {
                        if (!dTable.Columns.Contains(att.Key))
                            dTable.Columns.Add(att.Key);
                        dRow = att.Value;
                  });
                });
            return dTable;
      }
      // Gets the column names collection of the datatable
      public static IEnumerable GetColumnNames(this System.Data.DataTable dataTbl)
      {
            return dataTbl.Columns.Cast().Select(col => col.ColumnName);
      }
      // Writes an Excel file from the datatable (using late binding)
      public static void WriteXls(this System.Data.DataTable dataTbl, string filename, string sheetName, bool visible)
      {
            object mis = Type.Missing;
            object xlApp = LateBinding.GetOrCreateInstance("Excel.Application");
            xlApp.Set("DisplayAlerts", false);
            object workbooks = xlApp.Get("Workbooks");
            object workbook, worksheet;
            if (File.Exists(filename))
                workbook = workbooks.Invoke("Open", filename);
            else
                workbook = workbooks.Invoke("Add", mis);
            if (string.IsNullOrEmpty(sheetName))
                worksheet = workbook.Get("Activesheet");
            else
            {
                object worksheets = workbook.Get("Worksheets");
                try
                {
                  worksheet = worksheets.Get("Item", sheetName);
                  worksheet.Get("Cells").Invoke("Clear");
                }
                catch
                {
                  worksheet = worksheets.Invoke("Add", mis);
                  worksheet.Set("Name", sheetName);
                }
            }
            object range = worksheet.Get("Cells");
            dataTbl.GetColumnNames()
                .Iterate((name, i) => range.Get("Item", 1, i + 1).Set("Value2", name));
            dataTbl.Rows
                .Cast()
                .Iterate((row, i) => row.ItemArray
                  .Iterate((item, j) => range.Get("Item", i + 2, j + 1).Set("Value2", item)));
            xlApp.Set("DisplayAlerts", true);
            if (visible)
            {
                xlApp.Set("Visible", true);
            }
            else
            {
                if (File.Exists(filename))
                  workbook.Invoke("Save");
                else
                {
                  int fileFormat =
                        string.Compare("11.0", (string)xlApp.Get("Version"))string.Format("{0},{1}", s1, s2)));
                dataTbl.Rows
                  .Cast()
                  .Select(row => row.ItemArray.Aggregate((s1, s2) => string.Format("{0},{1}", s1, s2)))
                  .Iterate(line => writer.WriteLine(line));
            }
      }
      // Creates an AutoCAD Table from the datatable.
      public static Table ToAcadTable(this System.Data.DataTable dataTbl, double rowHeight, double columnWidth)
      {
            //return dataTbl.Rows.Cast().ToAcadTable(dataTbl.TableName, dataTbl.GetColumnNames(), rowHeight, columnWidth);
            Table tbl = new Table();
            tbl.Rows.Height = rowHeight;
            tbl.Columns.Width = columnWidth;
            tbl.InsertColumns(0, columnWidth, dataTbl.Columns.Count - 1);
            tbl.InsertRows(0, rowHeight, dataTbl.Rows.Count + 1);
            tbl.Cells.Value = dataTbl.TableName;
            dataTbl.GetColumnNames()
                .Iterate((name, i) => tbl.Cells.Value = name);
            dataTbl.Rows
                .Cast()
                .Iterate((row, i) =>
                  row.ItemArray.Iterate((item, j) =>
                        tbl.Cells.Value = item));
            return tbl;
      }
    }
}

LateBinding类提供了帮助程序,以更友好的风格编写后期绑定指令(感谢Thorsten和Tony T)。
using BF = System.Reflection.BindingFlags;
namespace AttributeExtraction
{
    public static class LateBinding
    {
      public static object GetInstance(string appName)
      {
            return System.Runtime.InteropServices.Marshal.GetActiveObject(appName);
      }
      public static object CreateInstance(string appName)
      {
            return System.Activator.CreateInstance(System.Type.GetTypeFromProgID(appName));
      }
      public static object GetOrCreateInstance(string appName)
      {
            try { return GetInstance(appName); }
            catch { return CreateInstance(appName); }
      }
      public static object Get(this object obj, string propName, params object[] parameter)
      {
            return obj.GetType().InvokeMember(propName, BF.GetProperty, null, obj, parameter);
      }
      public static void Set(this object obj, string propName, params object[] parameter)
      {
            obj.GetType().InvokeMember(propName, BF.SetProperty, null, obj, parameter);
      }
      public static object Invoke(this object obj, string methName, params object[] parameter)
      {
            return obj.GetType().InvokeMember(methName, BF.InvokeMethod, null, obj, parameter);
      }
      public static void ReleaseInstance(this object obj)
      {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
      }
    }
}

A 测试命令
using System.Linq;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace AttributeExtraction
{
    public class Commands
    {
      
      public void Test()
      {
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            TypedValue[] filter = { new TypedValue(0, "INSERT") };
            PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));
            if (psr.Status != PromptStatus.OK) return;
            PromptPointResult ppr = ed.GetPoint("\nInsertion point: ");
            if (ppr.Status != PromptStatus.OK) return;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                System.Data.DataTable dataTable = psr.Value.GetObjectIds()
                  .Select(id => new BlockAttribute(id.GetObject()))
                  .ToDataTable("Extraction");
                Table tbl = dataTable.ToAcadTable(9.0, 40.0);
                tbl.Position = ppr.Value.TransformBy(ed.CurrentUserCoordinateSystem);
                BlockTableRecord btr = db.CurrentSpaceId.GetObject(OpenMode.ForWrite);
                btr.AppendEntity(tbl);
                tr.AddNewlyCreatedDBObject(tbl, true);
                try
                {
                  string filename = (string)AcAp.GetSystemVariable("dwgprefix") + "Extraction.xls";
                  dataTable.WriteXls(filename, null, true);
                }
                catch
                {
                  AcAp.ShowAlertDialog("Failed to open Excel");
                }
                tr.Commit();
            }
      }
    }
}

kaefer 发表于 2011-11-6 02:53:55

我在上面的例子中添加了一些方法:System。Data.Datatable.WriteCsv(将数据表写入Csv文件)和System。Data.DataTable.WriteXls(将数据表写入Excel表中),它使用后期绑定来避免Excel版本依赖。LateBinding类提供了使后期绑定指令更具可读性的方法。

gile 发表于 2011-11-8 09:22:25


棒极了,这就是你的小例子:棒极了。
这里有一个基本的F#版本做同样的事情;它从选择集中的块参照中读取属性,对不同的属性集进行计数,将此信息存储在数据表中,并最终将其转换为AutoCAD表格。
我们的目标不是在gile的原创基础上进行改进(这几乎是不可能的),而是说明实现中的典型差异。
-用绑定函数代替扩展方法
-用流水线操作(| >)和函数组合(>>)代替方法链接
-与扩展方法相比,用相反的参数顺序来支持流水线操作
-使用支持IEquatable和IStructuralEquatable的数据类型,避免了对overriden Equals和GetHashCode方法的需要
-尝试“在小范围内”更具命令性,因为
对于bar中的foo...
读起来比
bar | > seq . ITER(fun foo-->...)
代码12]
已编辑: getObjects需要一个类型批注才能成为泛型
页: [1] 2
查看完整版本: . NET块例程