Итерация системных переменных AutoCAD через .NET, часть 2
В предыдущей части был предоставлен код, показывающий реализацию двух доступных механизмов итерации по системным переменным AutoCAD: SystemObects.Variables и новый класс SystemVariableEnumerator.
Сегодня мы посмотрим внимательнее на оба эти механизма, кратко сопоставив их возможности и результаты работы. За основу взят код из предыдущей части статьи. Код упрощен, удалены "проходы" по БД чертежа - все для улучшения сопоставимости результатов.
Ниже представлен код C# с обновленными вариантами команд ESV и ESV2, которые создают соответствующие txt-файлы в каталоге c:\temp. Это получается быстрее, чем вывод в командную строку Windows. Кроме того, игнорируется информация Primary/SecondaryType - все только ради того, чтобы получить сопоставимые результаты.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
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.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; } } } |
После запуска кода мы увидим, что команда ESV (использующая SystemObject.Variables) отработала быстрее, но нашла только 274 (при установленном SP1 для AutoCAD 2015 будет найдено 275 - включая CURSORBADGE) системные переменные. В то же время ESV2 обнаружит 912 (соответственно при установленном SP1 - 913) за сопоставимое время. Так что вопрос производительности можно сбросить со счетов.
Весьма интересно (и, можно сказать, даже обнадеживает), что новый механизм находит настолько больше системных переменных. С одной стороны, старый механизм (SystemObjects.Variables) позволяет менять значение системной переменной через возвращаемый объект:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
[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 ); } |
Но, с другой стороны, это работает только для подмножества системных переменных (и пока автор еще не выяснил, какие именно... Известно, что новый счетчик пропускает анонимные системные переменные, и все равно находит втрое больше переменных).
Если есть желание, можно рассмотреть подробнее результаты работы как команды ESV, так и команды ESV2.
Источник: http://through-the-interface.typepad.com/through_the_interface/2014/06/iterating-autocad-system-variables-using-net-part-2.html