找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1171|回复: 0

[分享] Iterating AutoCAD system variables using .NET – Part 2

[复制链接]

已领礼包: 859个

财富等级: 财运亨通

发表于 2014-7-30 21:58:53 来自手机 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 csharp 于 2014-7-31 08:06 编辑

http://through-the-interface.typepad.com/through_the_interface/2014/06/iterating-autocad-system-variables-using-net-part-2.html

In the last post we saw some code to exercise to two available system variable enumeration mechanisms in AutoCAD, SystemObjects.Variables and the new SystemVariableEnumerator class.

Today we’re going to take a closer look at these two mechanisms, briefly comparing their performance and results. I took some code from this previous post to measure elapsed time, deleting the “runs” database to simplify the code once I’d realised the performance was basically comparable.

Here’s the C# code, with the updated ESV and ESV2 commands which now create correspondingly named .txt files in c:\temp, rather than printing the results to the command-line (and with Primary/SecondaryType information ignored, to make the output consistent – and therefore diffable – between the two commands):

  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.ApplicationServices.Core;
  3. using Autodesk.AutoCAD.Geometry;
  4. using Autodesk.AutoCAD.Runtime;
  5. using System;
  6. using System.Diagnostics;
  7. using System.IO;
  8. using System.Text;

  9. namespace SystemVariableEnumeration
  10. {
  11.   public class Commands
  12.   {
  13.     public void MeasureTime(
  14.       Document doc, Func<int> func, string name
  15.     )
  16.     {
  17.       // Get the name of the running command(s)
  18.       // (might also have queried the CommandMethod attribute
  19.       // via reflection, but that would be a lot more work)

  20.       var cmd = (string)Application.GetSystemVariable("CMDNAMES");

  21.       // Start a Stopwatch to time the execution

  22.       var sw = new Stopwatch();
  23.       sw.Start();

  24.       // Run the function, getting back the count of the results

  25.       var cnt = func();

  26.       // Stop the Stopwatch and print the results to the command-line

  27.       sw.Stop();
  28.       doc.Editor.WriteMessage(
  29.         "\n{0} found {1} {2} in {3}.", cmd, cnt, name, sw.Elapsed
  30.       );
  31.     }

  32.     [CommandMethod("ESV")]
  33.     public void EnumerateSysVars()
  34.     {
  35.       var doc = Application.DocumentManager.MdiActiveDocument;
  36.       if (doc == null)
  37.         return;
  38.       MeasureTime(
  39.         doc,
  40.         () =>
  41.         {
  42.           int numVars = 0;
  43.           using (var sw = new StreamWriter("c:\\temp\\esv.txt"))
  44.           {
  45.             // Use the existing SystemObjects iteration mechanism

  46.             foreach (var v in SystemObjects.Variables)
  47.             {
  48.               sw.WriteLine(GetVariableInfo(v));
  49.               numVars++;
  50.             }
  51.           }
  52.           return numVars;
  53.         },
  54.         "variables"
  55.       );
  56.     }

  57.     [CommandMethod("ESV2")]
  58.     public void EnumerateSysVars2()
  59.     {
  60.       var doc = Application.DocumentManager.MdiActiveDocument;
  61.       if (doc == null)
  62.         return;
  63.       MeasureTime(
  64.         doc,
  65.         () =>
  66.         {
  67.           int numVars = 0;
  68.           using (var sw = new StreamWriter("c:\\temp\\esv2.txt"))
  69.           {
  70.             // Use the new system variable enumerator
  71.             var sve = new SystemVariableEnumerator();
  72.             while (sve.MoveNext())
  73.             {
  74.               var v = sve.Current;
  75.               if (v != null)
  76.               {
  77.                 sw.WriteLine(GetVariableInfo(v));
  78.                 numVars++;
  79.               }
  80.             }
  81.           }
  82.           return numVars;
  83.         },
  84.         "variables"
  85.       );
  86.     }

  87.     // Helper function to get the information for a particular
  88.     // variable

  89.     private static string GetVariableInfo(Variable v)
  90.     {
  91.       var t = GetType(v.PrimaryType);
  92.       var sb = new StringBuilder();
  93.       sb.AppendFormat(
  94.         "{0} ({1}): {2}", // Skip the additional type info
  95.         v.Name,
  96.         t == null ? "null" : t.Name,
  97.         /*v.PrimaryType, v.SecondaryType,*/ v.TypeFlags
  98.       );

  99.       if (v.Range != null)
  100.       {
  101.         sb.AppendFormat(
  102.           " [{0}...{1}]",
  103.           v.Range.LowerBound, v.Range.UpperBound
  104.         );
  105.       }
  106.       return sb.ToString();
  107.     }

  108.     // Determine the type of a system variable based on
  109.     // the internal representation

  110.     private static System.Type GetType(short v)
  111.     {
  112.       Type ret = null;
  113.       switch (v)
  114.       {
  115.         case 1:
  116.         case 5001: // RTREAL real number
  117.           {
  118.             ret = typeof(Double);
  119.             break;
  120.           }
  121.         case 2:
  122.         case 5002: // RTPOINT: 2D point X and Y only
  123.           {
  124.            ret = typeof(Point2d);
  125.             break;
  126.           }
  127.         case 3:
  128.         case 5003: // RTSHORT: short integer
  129.           {
  130.             ret = typeof(Int16);
  131.             break;
  132.           }
  133.         case 4:
  134.         case 5004: // RTANG: angle
  135.           {
  136.             ret = null; // Angle
  137.             break;
  138.           }
  139.         case 5:
  140.         case 5005: // RTSTR: string
  141.           {
  142.             ret = typeof(String);
  143.             break;
  144.           }
  145.         case 6:
  146.         case 5006: // RTENAME: entity name
  147.           {
  148.             ret = null;
  149.             break;
  150.           }
  151.         case 7:
  152.         case 5007: // RTPICKS: pick set
  153.           {
  154.             ret = null;
  155.             break;
  156.           }
  157.         case 8:
  158.         case 5008: // RTORIENT: orientation
  159.           {
  160.             ret = null; // Orientation
  161.             break;
  162.           }
  163.         case 9:

  164.         case 5009: // RT3DPOINT: 3D point - X, Y and Z
  165.           {
  166.             ret = typeof(Point3d);
  167.             break;
  168.           }
  169.         case 10:
  170.         case 5010: // RTLONG: long integer
  171.           {
  172.             ret = typeof(Int32);
  173.             break;
  174.           }

  175.         case 11:
  176.         case 5011: // 2D extents of some kind
  177.           {
  178.             ret = typeof(Point2d);
  179.             break;
  180.           }
  181.       }
  182.       return ret;
  183.     }
  184.   }
  185. }

When we run the code we see that the ESV command – the implementation using SystemObjects.Variables – returns the results more quickly but finds only 274 (or 275 with AutoCAD 2015 SP1 installed, as we have the new CURSORBADGE sysvar), whereas the ESV2 command finds 912 (or 913 with SP1) in a timespan that’s basically consistent with the fact there are more variables found. So performance isn’t an issue.

It is interesting (and somewhat reassuring) that the new enumerator finds so many more sysvars than the former mechanism. On the one hand the old collection allows you to modify a system variable’s value via the returned object…


  1. [CommandMethod("TOGCB")]
  2. public void ToggleCursorBadge()
  3. {
  4.   var doc = Application.DocumentManager.MdiActiveDocument;
  5.   if (doc == null)
  6.     return;
  7.   var ed = doc.Editor;
  8.   const string curbadge = "CURSORBADGE";

  9.   // Get our CURSORBADGE system variable object

  10.   var cb = SystemObjects.Variables[curbadge];

  11.   // Report its initial value

  12.   ed.WriteMessage(
  13.     "\nInitial value of {0} is {1}.", curbadge, cb.Value
  14.   );

  15.   // Set the new value, toggling between 1 & 2
  16.   // (with too many casts for my liking, but hey)

  17.   cb.Value = (short)((short)cb.Value == 1 ? 2 : 1);

  18.   // And report the new value to make sure it worked

  19.   ed.WriteMessage(

  20.     "\nNew value of {0} is {1}.", curbadge, cb.Value

  21.   );
  22. }


… but on the other hand this is really only for a subset of system variables (and I haven’t yet worked out which subset… I do know the new enumerator skips anonymous sysvars, and yet it still finds more than 3x the number).

In case you want to dig into the sysvars returned by each, here are the results for the ESV and the ESV2 commands. I did my own diff – and the results are returned in a consistent order, in that the ones found by ESV are at the end of the ones found by ESV2 – but I haven’t yet spent much time working out which ones are excluded from the old mechanism and why.

If anyone does look into this, please do post a comment: I’ll also post an update if I find out something further from my side.
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-5-22 03:52 , Processed in 0.248429 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表