EaBIM一直以来积极响应国家“十二五”推进建筑业信息化的号召,对建筑领域的信息技术开展深入技术交流和探讨!致力于打造“BIM-建筑师-生态技术”三位一体综合资源交流共享平台,希望为BIM与可持续设计理念及技术的普及做出微小的贡献!!!

萧闫子 发表于 2014-1-8 14:59:08

[实体对象] LINQ、Lambda、Delegate-实体过滤

Let us look at a cool AutoCAD .NET coding gadget in this post. It uses the cool modern LINQ technology to find some AutoCAD entities with a pretty complex filtering criteria, e.g. finding all circles with red or yellow color, with DASHED or DOT line type, on a unfrozen layer TEST, and having radiuses between 2.0 and 6.0 unit.In the old days without the LINQ technology, this is a not so straightforward and actually an error prone task. We generally had to use many out-of-dated ADS stuffs such as result buffer, DXF codes, selection set, and different sets of relational and logical operators which are not familiar to C# or C++ programmers at all, though they have been wrapped a bit and renamed in the AutoCAD .NET as such, TypedValue, DxfCode, SelectionFilter, etc.Furthermore, filtering color, layer and line type may be still possible to use the out of fashion result buffer and DXF code APIs, but for the circle radius comparison, a loop will be still necessary. Therefore, it just brings in unnecessary technical difficulties and makes the performance further worse if we choose to do so.With the wonderful LINQ technology handy, we do not have to care about these unfriendly legacy stuffs anymore. We can make the same work done more nicely, naturally and efficiently with less code in a single loop using the LINQ technology. Here we go.

private delegate bool InRange(double d);
private static Entity cachedEntity = null;
private static ObjectId cachedEntId = ObjectId.Null;
private static Entity GetEnt(Transaction tr, ObjectId id)
{
    if (cachedEntId != id || cachedEntity == null)
      cachedEntity = tr.GetObject(id, OpenMode.ForRead) as Entity;
    return cachedEntity;
}

public static void TestLinqInAutoCAD1_Method()
{
    Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
    try
    {
      ObjectId[] ids;
      InRange inRange2to6 = r => { return r >= 2.0 && r <= 6.0;};
      using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
      {
            BlockTable bt = tr.GetObject(HostApplicationServices.WorkingDatabase.BlockTableId, OpenMode.ForRead) as BlockTable;
            BlockTableRecord btr = tr.GetObject(bt, OpenMode.ForRead) as BlockTableRecord;
            var v = from ObjectId id in btr
                  where GetEnt(tr, id) is Circle &&
                            (new int[]{1,3}.Contains(GetEnt(tr, id).ColorIndex)) &&//Color Red or Yellow
                            GetEnt(tr, id).Layer == "TEST" &&                        //Layer 'TEST'
                            !(tr.GetObject(GetEnt(tr, id).LayerId, OpenMode.ForRead) as LayerTableRecord).IsFrozen &&    //Layer not frozen
                            (new string[]{"DASHED","DOT"}.Contains(GetEnt(tr, id).Linetype)) &&   //Linetype Dashed or Dotted
                            inRange2to6((GetEnt(tr, id) as Circle).Radius) //Circle radius in the range
                  select id;
            ids = v.ToArray();
            tr.Commit();
      }
      ed.WriteMessage(string.Format("\nThere are {0} circles meeting the filtering criteria.", ids.Length));
    }
    catch (System.Exception ex)
    {
      ed.WriteMessage(ex.ToString());
    }
}As can be seen, in the above succinct and cool code snippets, a few wonderful modern .NET technologies have been demonstrated such as LINQ, Lambda Expression and Delegate. Better, it is not just for new thing show-off. Instead, each cool tech applied here has its own very reason!In case there are some circles meeting the filtering criteria in the current drawing, the command may print out something onto the AutoCAD command line window as follows:Command: TestLinqInAutoCAD1There are 58 circles meeting the filtering criteria.
Command: -LAYERCurrent layer:"TEST"
Enter an option
[?/Make/Set/New/Rename/ON/OFF/Color/Ltype/LWeight/TRansparency/MATerial/Plot/Fre
eze/Thaw/LOck/Unlock/stAte/Description/rEconcile]: loEnter name list of layer(s) to lock or <select objects>: TEST
Enter an option
[?/Make/Set/New/Rename/ON/OFF/Color/Ltype/LWeight/TRansparency/MATerial/Plot/Fre
eze/Thaw/LOck/Unlock/stAte/Description/rEconcile]:Command: TESTLINQINAUTOCAD1There are 58 circles meeting the filtering criteria.
Command: layerCommand: -LAYERCurrent layer:"TEST"
Enter an option
[?/Make/Set/New/Rename/ON/OFF/Color/Ltype/LWeight/TRansparency/MATerial/Plot/Fre
eze/Thaw/LOck/Unlock/stAte/Description/rEconcile]: sEnter layer name to make current or <select object>: 0
Enter an option
[?/Make/Set/New/Rename/ON/OFF/Color/Ltype/LWeight/TRansparency/MATerial/Plot/Fre
eze/Thaw/LOck/Unlock/stAte/Description/rEconcile]: freezeEnter name list of layer(s) to freeze or <select objects>: test
Enter an option
[?/Make/Set/New/Rename/ON/OFF/Color/Ltype/LWeight/TRansparency/MATerial/Plot/Fre
eze/Thaw/LOck/Unlock/stAte/Description/rEconcile]:Command: TESTLINQINAUTOCAD1There are 0 circles meeting the filtering criteria.
Command: -LAYERCurrent layer:"0"
Enter an option
[?/Make/Set/New/Rename/ON/OFF/Color/Ltype/LWeight/TRansparency/MATerial/Plot/Fre
eze/Thaw/LOck/Unlock/stAte/Description/rEconcile]: thawEnter name list of layer(s) to thaw: test
Enter an option
[?/Make/Set/New/Rename/ON/OFF/Color/Ltype/LWeight/TRansparency/MATerial/Plot/Fre
eze/Thaw/LOck/Unlock/stAte/Description/rEconcile]:Command: TESTLINQINAUTOCAD1There are 58 circles meeting the filtering criteria.By the way, besides better code conciseness, cleanness, and readability in the code as demonstrated here, in terms of performance, I bet the new way is way better as well, though I haven’t done any experiment about it. If interested in, please feel free to go ahead and give it a shot.Enjoy it! More coding gadgets will be created and demonstrated in the future. Please stay tuned.The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard)provides various project wizards, item wizards, coders and widgets to help program AutoCAD .NET addins.
页: [1]
查看完整版本: [实体对象] LINQ、Lambda、Delegate-实体过滤