Каталоги MEF

50

Каталог определяет то, где MEF ищет запрошенные части. В примере приложения каталог DirectoryCatalog используется для загрузки сборок с частями из указанной папки. С помощью события Changed из DirectoryCatalog можно получить информацию об изменениях и выполнить итерацию по всем добавленным и удаленным определениям.

DirectoryCatalog сам не регистрирует изменений в файловой системе. Вместо этого вы должны вызывать метод Refresh() класса DirectoryCatalog, и если изменения произошли с момента последнего чтения, инициируются события Changing и Changed.

private void InitializeContainer()
        {
            catalog = new DirectoryCatalog(Properties.Settings.Default.AddInDirectory);
            catalog.Changed += (sender, e) =>
                {
                    var sb = new StringBuilder();
                    
                    foreach (var definition in e.AddedDefinitions)
                    {    
                        foreach (var metadata in definition.Metadata)
                        {
                            sb.AppendFormat("added definition with metadata - key: {0}, value: {1}\n", metadata.Key, metadata.Value);           
                        }
                    }
                    
                    foreach (var definition in e.RemovedDefinitions)
                    {
                        foreach (var metadata in definition.Metadata)
                        {
                            sb.AppendFormat("removed definition with metadata - key: {0}, value: {1}\n", metadata.Key, metadata.Value);
                        }
                    }
                    this.textStatus.Text += sb.ToString();
                };
            container = new CompositionContainer(catalog);
            ...

Чтобы получить немедленное уведомление о новых дополнениях, загруженных в папку, можно воспользоваться System.IO.FileSystemWatcher для регистрации изменений в папке дополнений и вызвать метод Refresh класса DirectoryCatalog в событии Changed класса FileSystemWatcher.

CompositionContainer необходим только каталог ComposablePartCatalog для нахождения частей. Класс DirectoryCatalog унаследован от ComposablePartCatalog. Другими типами каталогов являются AssemblyCatalog, TypeCatalog и AggregateCatalog. Давайте сравним все эти каталоги:

DirectoryCatalog

ищет части внутри папки.

AssemblyCatalog

ищет части непосредственно внутри ссылаемой сборки. В противоположность DirectoryCatalog, где сборки могут изменяться в папке во время выполнения, AssemblyCatalog является неизменяемым, и его части не могут меняться.

TypeCatalog

ищет импорты внутри списка типов. Конструктору этого каталога может передаваться IEnumerable<Type>.

AggregateCatalog

представляет собой каталог каталогов. Он может создаваться из множества объектов ComposablePartCatalog и производит поиск во всех этих каталогах. Например, можно создать объект AssemblyCatalog для поиска импортов внутри сборки, два объекта DirectoryCatalog для поиска в двух разных папках и AggregateCatalog, комбинирующий эти три каталога для поиска импорта.

При запуске примера приложения загружается сборка SimpleCalculator, и появится возможность выполнять некоторые вычисления с помощью операций, поддерживаемых дополнением. Через меню AddIns (Дополнения) можно запустить дополнение, которое реализует интерфейс ICalculatorExtender, и видеть пользовательский интерфейс этого дополнения в элементе управления с вкладками. Информация об экспортах и изменениях в папке каталога отображается в поле состояния внизу. Можно также удалить дополнение ICalculatorExtender из папки дополнения (пока приложение не запущено), скопировать дополнение в папку во время его работы, и выполнить обновление, что-бы увидеть новое дополнение во время выполнения.

Пройди тесты
Лучший чат для C# программистов