Программное определение дублированных имен .NET команд
Неприятен факт связанный с атрибутом CommandMethod в AutoCAD .NET сборке: в нем может быть две разных команды имеющих одно имя но разные методы. Например, как в следующем коде:- [CommandMethod("Test")]
- public void SomeMethod()
- {
- // Реализация ...
- }
- [CommandMethod("Test")]
- public void SomeOtherMethod()
- {
- // Реализация ...
- }
Что будет если мы попробуем загрузить dll-файл, содержащий этот код, в AutoCAD? Этот код прекрасно скомпилируется, но при загрузке появятся сообщения об ошибке:
Но нет способа узнать какая команда привела к сообщению об исключении. Несложно определить это в данном сценарии, но в моем случае я работаю с .NET-файлом, в котором определены сотни команд, распределенных среди десятков файлов. Так что если я для тестирования дублирую часть кода, я могу случайно продублировать и имя команды, которую затем сложно найти.
В качестве решения для поиска дубликатов можно предложить использовать возможности .NET Reflection. Это делается следующим куском кода: необходимо создать отдельный .NET dll-файл и загрузить dll-файл содержащий дубликаты, используя FindCmdDuplicates (path):
- [CommandMethod("FindCmdDuplicates")]
- public void FindCmdDuplicatesCmd()
- {
- string asmPath = SelectAssembly();
- if (asmPath == null)
- return;
- FindCmdDuplicates(asmPath);
- }
- private string SelectAssembly()
- {
- System.Windows.Forms.OpenFileDialog dlg =
- new System.Windows.Forms.OpenFileDialog();
- dlg.Title = "Загрузка файла сборки ";
- dlg.InitialDirectory = Environment.GetFolderPath(
- Environment.SpecialFolder.Desktop);
- dlg.Filter = ".Net сборка (*.dll)|*.dll";
- dlg.FilterIndex = 1;
- dlg.RestoreDirectory = true;
- while (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
- {
- try
- {
- AssemblyName asmName =
- AssemblyName.GetAssemblyName(dlg.FileName);
- return dlg.FileName;
- }
- catch (BadImageFormatException ex)
- {
- System.Windows.Forms.MessageBox.Show(
- "Извините, но это неверная .NET сборка...",
- "Неверная сборка",
- System.Windows.Forms.MessageBoxButtons.OK,
- System.Windows.Forms.MessageBoxIcon.Error);
- }
- }
- return null;
- }
- public void FindCmdDuplicates(string asmPath)
- {
- Dictionary<string, List<MethodInfo>> map =
- new Dictionary<string, List<MethodInfo>>();
- Assembly asm = Assembly.LoadFile(asmPath);
- Type[] expTypes = asm.GetTypes();
- foreach (Type type in expTypes)
- {
- MethodInfo[] methods = type.GetMethods();
- foreach (MethodInfo method in methods)
- {
- CommandMethodAttribute attribute =
- GetCommandMethodAttribute(method);
- if (attribute == null)
- continue;
- if (!map.ContainsKey(attribute.GlobalName))
- {
- var methodInfo = new List<MethodInfo>();
- map.Add(attribute.GlobalName, methodInfo);
- }
- map[attribute.GlobalName].Add(method);
- }
- }
- Document doc = Application.DocumentManager.MdiActiveDocument;
- Editor ed = doc.Editor;
- foreach (var keyValuePair in map)
- {
- if (keyValuePair.Value.Count > 1)
- {
- ed.WriteMessage(
- "\nДублированный атрибут: " + keyValuePair.Key);
- foreach (var method in keyValuePair.Value)
- {
- ed.WriteMessage(
- "\n – Метод: " + method.Name);
- }
- }
- }
- }
- public CommandMethodAttribute GetCommandMethodAttribute(
- MethodInfo method)
- {
- object[] attributes = method.GetCustomAttributes(true);
- foreach (object attribute in attributes)
- {
- if (attribute is CommandMethodAttribute)
- {
- return attribute as CommandMethodAttribute;
- }
- }
- return null;
- }
Источник: http://adndevblog.typepad.com/autocad/2014/01/detecting-net-command-duplicates-programmatically.html
Обсуждение: http://adn-cis.org/forum/index.php?topic=513
Опубликовано 07.02.2014Отредактировано 07.02.2014 в 03:18:12