Здравствуйте. Интересует вот какой вопрос. Хотелось бы по правильному организовать написание крупных плагинов. Для этого хочется иметь модульную структуру приложения. То есть, разбить функции плагина на набор сервисов (или подмодулей), которые я регистрирую с помощью какого-нибудь IoC контейнера в методе
Initialize() сборки. Предположим, что у нас в плагине есть три сервиса. Один отвечает за какую-нибудь хитрую подсветку и зуммирование на чертеже и реализует интерфейс
IHighlighter, остальные два (
Module1,
Module2) выполняют какую то работу в командах (то есть, у них есть методы, помеченные атрибутом
[CommandMethod("")]), выбирая элементы чертежа и подвечивая их с помощью объекта класса, реализующего
IHighlighter. Хотелось бы иметь возможность регистрировать их и проводить необходимую инициализацию:
public class MISAEApp : IExtensionApplication
{
public void Initialize()
{
var container = new SomeServiceContainer();
container.Register<IHighlighter,MyHighlighter>();
container.Register<Module1>();
}
public void Terminate()
{
}
}
Первый вопрос заключается в том, что хотелось бы иметь возможность указать автокаду не регистрировать команды
Module2,не смотря на то, что у него есть методы, помеченные атрибутом
[CommandMethod("")] , если он не подключен мною в методе
Initialize(). На сегодняшний день я знаю только один способ сделать это. Пометить нужные мне классы команд атрибутом
CommandClass. Но мне кажется , что это костыль. Ведь если я хочу по какой то причине выключить модуль, мне надо лезть в код класса команд и убирать этот аттрибут. А потом, если я хочу включить модуль, то, несмотря на мои настройки инициализации мне надо слазить в этот класс и пометить его этим аттрибутом.
Второй вопрос сложнее . Хотелось бы привести пример желаемого и не желаемого кода
Module1 :
// Круто
public class Module1
{
IHighlighter Highlighter;
public ModuleCommands(IHighlighter highlighter)
{
Highlighter = highlighter;
}
[CommandMethod("cmd")]
public void MyCmd()
{
var res = doSomeWork();
Highlighter.Show(res);
}
private object doSomeWork()
{
// dosomework;
}
}
// Не круто
public class Module1
{
IHighlighter Highlighter
{
get
{
return SomeServiceContainer.GetInstance<IHighlighter>();
}
}
[CommandMethod("cmd")]
public void MyCmd()
{
var res = doSomeWork();
Highlighter.Show(res);
}
private object doSomeWork()
{
// dosomework;
}
}
Второй вариант меня не очень устраивает, поскольку это прямой пример антипаттерна
ServiceLocator. Хочу инжектировать зависимости в конструкторе. Тобишь, иметь какую нибудь фабрику, которая при вызове команды создает нужный класс команд. Но у меня с этим две проблемы:
- Я вообще не знаю, как управлять созданием класса команд.
- Автокад создает класс команд один раз, при первом вызове команды, содержащейся в нем. А потом держит в памяти экземпляр этого класса. А мне надо, чтоб класс создавался по новой, при каждом вызове команды.
Я считаю, что если решить этот вопрос (если возможно) и сделать из классов команд подобие контроллеров в ASP.Net MVC (если кто знаком с технологией), то можно сделать разработку плагинов понятнее и улучшить тестируемость самих плагинов.