Как мой преподаватель структуры данных, на которого указывают сегодня: Дайте инструкции относительно того, как Ваша программа работает среднему пользователю. Мы программисты часто думают, что мы довольно логичны с нашими программами, но средний пользователь, вероятно, не будет знать, что сделать.
Взгляните на Composite WPF . Использование чего-то вроде этого должно позволить вам определить вкладки для каждого плагина. В этом случае приложение оболочки будет отвечать только за загрузку каждого модуля в соответствующее представление этого модуля.
Microsoft поощряет разработчиков использовать этот подход - Руководство по составным приложениям для WPF и Silverlight
Я предлагаю взглянуть на то, как Castle Windsor структура DI / IoC справляется с дополнительными требованиями, которые вам нужны, и, возможно, рассмотреть возможность ее использования.
Но в целом ваши плагины должны поддерживать интерфейс, свойство или конструктор, с помощью которого вы можете внедрить объект конфигурации из общего источника, такого как файл app.config.
Mono.Addins - очень хорошая библиотека для реализации любых плагинов (даже тех, которые могут обновляться с веб-сайта). MEF тоже может это сделать, но на более низком уровне. Но MEF будет частью .NET 4.
Определите интерфейс для настраиваемых подключаемых модулей:
public interface IConfigurable
{
public void LoadConfig(string configFile);
public void ShowConfig();
// Form or whatever, allows you to integrate it into another control
public Form GetConfigWindow();
}
Просто вызовите интерфейс IConfigurable для настраиваемых подключаемых модулей.
Если вы хотите, вы можете заставить интерфейс работать другим способом, сделав основное приложение предоставить плагину контейнер (например, фрейм или док-станцию), чтобы он тоже чувствовал себя, но я бы порекомендовал другой способ.
public interface IConfigurable
{
void LoadConfig(string configFile);
void ShowConfig(DockPanel configurationPanel);
}
Наконец, вы можете сделать это сложным путем, определив, что именно плагин может предложить как вариант конфигурации.
public interface IMainConfigInterop
{
void AddConfigurationCheckBox(ConfigurationText text);
void AddConfigurationRadioButton(ConfigurationText text);
void AddConfigurationSpinEdit(Confguration text, int minValue, int maxValue);
}
public interface IConfigurable
{
void LoadConfig(string configFile);
void PrepareConfigWindow(IMainConfigInterop configInterop);
}
Конечно, этот параметр является более ограничительным и более безопасным, поскольку вы можете полностью ограничить то, как плагин может взаимодействовать с окном конфигурации.
Как я реализовал свою реализацию для решения точно такой же проблемы (поскольку dll-файлы не могут читать свои конфигурационные файлы), я определил два интерфейса, один для плагина IPlugin
и один для хоста IHost
. Плагин был создан и инициализирован со ссылкой на хост (реализующий интерфейс IHost
). Затем
interface IHost {
string[] ReadConfiguration(string fileName);
}
interface IPlugin {
void Initialize(IHost host);
}
class MyPlugin : IPlugin {
public void Initialize(IHost host) {
host.ReadConfiguration("myplygin.config");
}
}
IHost
может предоставлять любые общие функции, которые нужны всем вашим плагинам (например, чтение и запись конфигурации), и плагины также более осведомлены о вашем хост-приложении, не привязываясь к конкретному хост-приложению. Например, вы можете написать приложение Web Service и одно приложение Forms, которые используют один и тот же API плагина.
Другим способом было бы инициализировать плагин с информацией о конфигурации, считываемой хост-приложением, однако мне нужно было, чтобы плагин мог читать/писать свою конфигурацию и выполнять другие действия по требованию.