Эта форма 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));

 }

}

Перейти на страницу:

Похожие книги