- UID
- 658062
- 积分
- 2147
- 精华
- 贡献
-
- 威望
-
- 活跃度
-
- D豆
-
- 在线时间
- 小时
- 注册时间
- 2008-10-22
- 最后登录
- 1970-1-1
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本帖最后由 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):
- using Autodesk.AutoCAD.ApplicationServices;
- using Autodesk.AutoCAD.ApplicationServices.Core;
- using Autodesk.AutoCAD.Geometry;
- using Autodesk.AutoCAD.Runtime;
- using System;
- using System.Diagnostics;
- using System.IO;
- using System.Text;
- namespace SystemVariableEnumeration
- {
- public class Commands
- {
- public void MeasureTime(
- Document doc, Func<int> func, string name
- )
- {
- // Get the name of the running command(s)
- // (might also have queried the CommandMethod attribute
- // via reflection, but that would be a lot more work)
- var cmd = (string)Application.GetSystemVariable("CMDNAMES");
- // Start a Stopwatch to time the execution
- var sw = new Stopwatch();
- sw.Start();
- // Run the function, getting back the count of the results
- var cnt = func();
- // Stop the Stopwatch and print the results to the command-line
- sw.Stop();
- doc.Editor.WriteMessage(
- "\n{0} found {1} {2} in {3}.", cmd, cnt, name, sw.Elapsed
- );
- }
- [CommandMethod("ESV")]
- public void EnumerateSysVars()
- {
- var doc = Application.DocumentManager.MdiActiveDocument;
- if (doc == null)
- return;
- MeasureTime(
- doc,
- () =>
- {
- int numVars = 0;
- using (var sw = new StreamWriter("c:\\temp\\esv.txt"))
- {
- // Use the existing SystemObjects iteration mechanism
- foreach (var v in SystemObjects.Variables)
- {
- sw.WriteLine(GetVariableInfo(v));
- numVars++;
- }
- }
- return numVars;
- },
- "variables"
- );
- }
- [CommandMethod("ESV2")]
- public void EnumerateSysVars2()
- {
- var doc = Application.DocumentManager.MdiActiveDocument;
- if (doc == null)
- return;
- MeasureTime(
- doc,
- () =>
- {
- int numVars = 0;
- using (var sw = new StreamWriter("c:\\temp\\esv2.txt"))
- {
- // Use the new system variable enumerator
- var sve = new SystemVariableEnumerator();
- while (sve.MoveNext())
- {
- var v = sve.Current;
- if (v != null)
- {
- sw.WriteLine(GetVariableInfo(v));
- numVars++;
- }
- }
- }
- return numVars;
- },
- "variables"
- );
- }
- // Helper function to get the information for a particular
- // variable
- private static string GetVariableInfo(Variable v)
- {
- var t = GetType(v.PrimaryType);
- var sb = new StringBuilder();
- sb.AppendFormat(
- "{0} ({1}): {2}", // Skip the additional type info
- v.Name,
- t == null ? "null" : t.Name,
- /*v.PrimaryType, v.SecondaryType,*/ v.TypeFlags
- );
- if (v.Range != null)
- {
- sb.AppendFormat(
- " [{0}...{1}]",
- v.Range.LowerBound, v.Range.UpperBound
- );
- }
- return sb.ToString();
- }
- // Determine the type of a system variable based on
- // the internal representation
- private static System.Type GetType(short v)
- {
- Type ret = null;
- switch (v)
- {
- case 1:
- case 5001: // RTREAL real number
- {
- ret = typeof(Double);
- break;
- }
- case 2:
- case 5002: // RTPOINT: 2D point X and Y only
- {
- ret = typeof(Point2d);
- break;
- }
- case 3:
- case 5003: // RTSHORT: short integer
- {
- ret = typeof(Int16);
- break;
- }
- case 4:
- case 5004: // RTANG: angle
- {
- ret = null; // Angle
- break;
- }
- case 5:
- case 5005: // RTSTR: string
- {
- ret = typeof(String);
- break;
- }
- case 6:
- case 5006: // RTENAME: entity name
- {
- ret = null;
- break;
- }
- case 7:
- case 5007: // RTPICKS: pick set
- {
- ret = null;
- break;
- }
- case 8:
- case 5008: // RTORIENT: orientation
- {
- ret = null; // Orientation
- break;
- }
- case 9:
- case 5009: // RT3DPOINT: 3D point - X, Y and Z
- {
- ret = typeof(Point3d);
- break;
- }
- case 10:
- case 5010: // RTLONG: long integer
- {
- ret = typeof(Int32);
- break;
- }
- case 11:
- case 5011: // 2D extents of some kind
- {
- ret = typeof(Point2d);
- break;
- }
- }
- return ret;
- }
- }
- }
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…
- [CommandMethod("TOGCB")]
- public void ToggleCursorBadge()
- {
- var doc = Application.DocumentManager.MdiActiveDocument;
- if (doc == null)
- return;
- var ed = doc.Editor;
- const string curbadge = "CURSORBADGE";
- // Get our CURSORBADGE system variable object
- var cb = SystemObjects.Variables[curbadge];
- // Report its initial value
- ed.WriteMessage(
- "\nInitial value of {0} is {1}.", curbadge, cb.Value
- );
- // Set the new value, toggling between 1 & 2
- // (with too many casts for my liking, but hey)
- cb.Value = (short)((short)cb.Value == 1 ? 2 : 1);
- // And report the new value to make sure it worked
- ed.WriteMessage(
- "\nNew value of {0} is {1}.", curbadge, cb.Value
- );
- }
… 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.
|
|