Создание расширяемого приложения Windows Forms

We use cookies. Read the Privacy and Cookie Policy

Создание расширяемого приложения Windows Forms

Заключительным шагом будет создание приложения Windows Forms, которое позволит пользователю выбрать подключаемый блок с помощью стандартного диалогового окна открытия файла Windows. Создав новое приложение Windows Forms (с именем MyExtendableApp), добавите ссылку на компоновочный блок CommonSnappableTypes.dll, но не устанавливайте ссылок на библиотеки программного кода CSharpSnapIn.dll и VbNetSnapIn.dll. Помните о том, что целью создания этого приложения является демонстрация динамического связывания и отображения при выяснении возможности подключения независимых двоичных блоков, созданных сторонними производителями.

Снова подчеркнем, что здесь не рассматриваются детали процесса построения приложений Windows Forms. Тем не менее, предполагается, что вы поместите компонент MenuStrip в окно формы и определите с его помощью меню Сервис, которое будет содержать единственный пункт Подключаемый модуль (рис. 12.11).

Рис. 12.11. Исходный графический интерфейс MyExtendableApp

Эта форма Windows должна также содержать тип Listbox (которому здесь назначено имя lstLoadedSnapIns), используемый для отображения имен подключаемых модулей, загружаемых пользователем. На рис. 12.12 показан окончательный вид графического интерфейса приложения, о котором идет речь.

Рис. 12.12. Окончательный вид графического интерфейса MyExtendableApp

Программный код для обработки выбора Сервис?Подключаемый модуль из меню (этот программный код можно создать с помощью двойного щелчка на пункте меню в окне проектирования формы), отображает диалоговое окно Открытие файла и читает путь к выбранному файлу. Соответствующая строка пути затем посылается вспомогательной функции LoadExternalModule() для обработки. Метод возвращает false (ложь), если он не обнаруживает класс, реализующий IAppFunctionality.

private void snapInModuleToolStripMenuItem_Click(object sender, EventArgs e) {

 // Позволяет пользователю выбрать компоновочный блок для загрузки.

 OpenFileDialog dlg = new OpenFileDialog();

 if (dlg.ShowDialog() == DialogResult.OK) {

  if (LoadExternalModule(dlg.FileName) == false) MessageBox.Show("Нет реализации IAppFunctionality!");

 }

}

Метод LoadExternalModule() решает следующие задачи.

• Динамически загружает компоновочный блок в память.

• Выясняет, содержит ли компоновочный блок тип, реализующий IAppFunctionality

Если тип, реализующий IAppFunctionality, обнаружен, вызывается метод DoIt(), и абсолютное имя типа добавляется в Listbox (заметьте, что цикл for должен выполнить проход по всем типам компоновочного блока, чтобы учесть возможность наличия в одном компоновочном блоке нескольких модулей расширения).

private bool LoadExternalModule(string path) {

 bool foundSnapIn = false;

 IAppFunctionality itfAppFx;

 // Динамическая загрузка выбранного компоновочного блока.

 Assembly theSnapInAsm = Assembly.LоadFrom(path);

 // Получение всех типов компоновочного блока.

 Tуре[] theTypes = theSnapInAsm.GetTypes();

 // Поиск типа с реализацией IAppFunctionality.

 for (int i = 0; i ‹ theTypes.Length; i++) {

  Type t = theTypes[i].GetInterface("IAppFunctionality");

  if (t != null) {

   foundSnapIn = true;

   // Динамическое связывание для создания типа.

   object о = theSnapInAsm.CreateInstance(theTypes[i].FullName);

   // Вызов DoIt() через интерфейс.

   itfAppFx = о as IAppFunctionality;

   itfAppFx.DoIt();

   lstLoadedSnapIns.Items.Add(theTypes[i].FullName);

  }

 }

 return foundSnapIn;

}

Теперь вы можете выполнить свое приложение. При выборе компоновочных блоков CSharpSnapIn.dll и VbNetSnapIn.dll вы должны увидеть соответствующее сообщение. На рис. 12.13 показан один из возможных вариантов выполнения.

Рис. 12.13. Подключение внешних компоновочных блоков

Завершающей задачей будет отображение метаданных, соответствующих атрибуту [CompanyInfo]. Для этого просто обновите LoadExternalModule(), чтобы перед выходом из контекста if вызывалась новая вспомогательная функция DisplayCompanyData(). Эта функция имеет один параметр типа System.Type.

private bool LoadExternalModule(string path) {

 …

 if (t != null) {

  …

  // Отображение информации о компании.

  DisplayCompanyData(theTypes[i]);

 }

 return foundSnapIn;

}

Для поступающего на вход типа просто отобразите атрибут [CompanyInfo].

private void DisplayCompanyData(Type t) {

 // Получение данных [CompanyInfo].

 object[] customAtts = t.GetCustomAttributes(false);

 // Вывод данных.

 foreach (CompanyInfoAttribute с in customAtts) {

  MessageBox.Show(с.Url, String.Format("Дополнительные сведения о {0} ищите по адресу", с.Name));

 }

}

Превосходно! На этом рассмотрение примера завершается. Я надеюсь, что к этому моменту нашего обсуждения вы осознаете, что подходы, представленные в этой главе, могут найти применение и на практике, а не только при разработке средств построения программ.

Исходный код. Программный код приложений CommonSnappableTypes, CSharpSnapIn, VbNetSnapIn и MyExtendableApp размещен в подкаталоге, соответствующем главе 12.