using System;
using CommonSnappableTypes;
namespace CSharpSnapIn
{
[CompanyInfo(CompanyName = "FooBar", CompanyUrl = "www.FooBar.com")]
public class CSharpModule : IAppFunctionality
{
void IAppFunctionality.DoIt()
{
Console.WriteLine("You have just used the C# snap-in!");
}
}
}
Обратите внимание на явную реализацию интерфейса
IAppFunctionality
(см. главу 8). Поступать так необязательно; тем не менее, идея заключается в том, что единственной частью системы, которая нуждается в прямом взаимодействии с упомянутым интерфейсным типом, будет размещающее приложение. Благодаря явной реализации интерфейса
IAppFunctionality
метод
DoIt()
не доступен напрямую из типа
CSharpModule
.
Построение оснастки на Visual Basic
Теперь перейдите к проекту
VBSnapIn
. Удалите файл
Class1.vb
и добавьте новый файл по имени
VBSnapIn.vb
. Код Visual Basic столь же прост:
Imports CommonSnappableTypes
<CompanyInfo(CompanyName:="Chucky's Software", CompanyUrl:="www.ChuckySoft.com")>
Public Class VBSnapIn
Implements IAppFunctionality
Public Sub DoIt() Implements CommonSnappableTypes.IAppFunctionality.DoIt
Console.WriteLine("You have just used the VB snap in!")
End Sub
End Class
Как видите, применение атрибутов в синтаксисе Visual Basic требует указания угловых скобок (
<>
), а не квадратных (
[]
). Кроме того, для реализации интерфейсных типов заданным классом или структурой используется ключевое слово
Implements
.
Добавление кода для ExtendableApp
Последним обновляемым проектом является консольное приложение C# (
MyExtendableApp
). После добавления к решению консольного приложения
MyExtendableApp
и установки его как стартового проекта добавьте ссылку на проект
CommonSnappableTypes
, но не на
CSharpSnapIn.dll
или
VbSnapIn.dll
. Модифицируйте операторы
using
в начале файла
Program.cs
, как показано ниже:
using System;
using System.Linq;
using System.Reflection;
using CommonSnappableTypes;
Метод
LoadExternalModule()
выполняет следующие действия:
• динамически загружает в память выбранную сборку;
• определяет, содержит ли сборка типы, реализующие интерфейс
IAppFunctionality
;
• создает экземпляр типа, используя позднее связывание.
Если обнаружен тип, реализующий
IAppFunctionality
, тогда вызывается метод
DoIt()
и найденный тип передается методу
DisplayCompanyData()
для вывода дополнительной информации о нем посредством рефлексии.
static void LoadExternalModule(string assemblyName)
{
Assembly theSnapInAsm = null;
try
{
// Динамически загрузить выбранную сборку.
theSnapInAsm = Assembly.LoadFrom(assemblyName);
}
catch (Exception ex)
{
// Ошибка при загрузке оснастки
Console.WriteLine($"An error occurred loading the snapin: {ex.Message}");
return;
}
// Получить все совместимые c IAppFunctionality классы в сборке.
var theClassTypes = theSnapInAsm
.GetTypes()
.Where(t => t.IsClass && (t.GetInterface("IAppFunctionality") != null))
.ToList();
if (!theClassTypes.Any())
{
Console.WriteLine("Nothing implements IAppFunctionality!");
// Ни один класс не реализует IAppFunctionality!
}
// Создать объект и вызвать метод DoIt().
foreach (Type t in theClassTypes)
{
/// Использовать позднее связывание для создания экземпляра типа.
IAppFunctionality itfApp =
(IAppFunctionality)
theSnapInAsm.CreateInstance(t.FullName,
true);
itfApp?.DoIt();
// Отобразить информацию о компании.
DisplayCompanyData(t);
}
}