MEF и DirectoryCatalog

Есть ли способ безопасно использовать DirectoryCatalog для обработки, если каталог не существует?

Вот пример кода того, как настроен мой контейнер:

    //Create an assembly catalog of the assemblies with exports
    var catalog = new AggregateCatalog(
        new AssemblyCatalog(Assembly.GetExecutingAssembly()),
        new AssemblyCatalog(Assembly.Load("My.Second.Assembly")),
        new DirectoryCatalog("Plugins", "*.dll"));

    //Create a composition container
    var container = new CompositionContainer(catalog);

Но возникает исключение, если каталог не существует, и я хотел бы игнорировать эту ошибку.


person jonathanpeppers    schedule 19.07.2011    source источник
comment
Есть ли причина, по которой вы не можете просто проверить существование каталога перед настройкой AggregateCatalog?   -  person Barry Wark    schedule 20.07.2011
comment
Я бы хотел, но, похоже, в DirectoryCatalog встроена некоторая хорошая логика для получения правильного пути (а не просто текущего каталога). Кто-нибудь знает, что он использует? Место сборки?   -  person jonathanpeppers    schedule 20.07.2011
comment
Я прокомментировал ответ ниже, но я также упомяну об этом здесь ... вы не должны полагаться только на проверку существования каталогов. Вы должны учитывать любые исключения ввода-вывода, которые вы хотите обработать (например, если каталог не существует, или если файлы заблокированы, или UAT и т. д.)   -  person myermian    schedule 25.03.2014


Ответы (1)


По-видимому, нет, если выброшено исключение. Просто создайте каталог перед запуском установки контейнера MEF, и тогда ошибка не будет выдана.

Согласно документации:

Путь должен быть абсолютным или относительным для AppDomain.BaseDirectory.

PsuedoCode для проверки каталога:

    string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins");

    //Check the directory exists
    if (!Directory.Exists(path))
    {
        Directory.CreateDirectory(path);
    }

    //Create an assembly catalog of the assemblies with exports
    var catalog = new AggregateCatalog(
        new AssemblyCatalog(Assembly.GetExecutingAssembly()),
        new AssemblyCatalog(Assembly.Load("My.Other.Assembly")),
        new DirectoryCatalog(path, "*.dll"));

    //Create a composition container
    _container = new CompositionContainer(catalog);  
person Jon Raynor    schedule 19.07.2011
comment
Смотрите мой комментарий выше. Какой метод использует DirectoryCatalog для расширения полного пути? - person jonathanpeppers; 20.07.2011
comment
Он либо абсолютный, либо относительный для System.AppDomain.BaseDirectory. - person Jon Raynor; 20.07.2011
comment
Отметил вас как ответ. Я обновил ваш код в вашем ответе на то, что я использовал. - person jonathanpeppers; 20.07.2011
comment
Вы никогда не должны полагаться на проверку условий гонки, такую ​​как Directory.Exists(path). Между этим вызовом и следующим вызовом каталог может не существовать. Вместо этого используйте обработку исключений, чтобы поймать возможное исключение и обработать его соответствующим образом... см. этот ответ: stackoverflow.com/a/9003962/347172 - person myermian; 25.03.2014
comment
Directory.CreateDirectory завершится ошибкой, если небольшая вероятность того, что каталог будет создан между проверкой существования и вызовом createdirectory. Итак, да, вокруг этого кода или где-то в стеке вызовов должен быть блок try catch. - person Jon Raynor; 08.12.2014
comment
@JonRaynor Вы когда-нибудь находили время, чтобы прочитать документы и провести тестирование с Directory.CreateDirectory? Из документов: «Если каталог уже существует, этот метод не создает новый каталог, а возвращает объект DirectoryInfo для существующего каталога». Из тестирования: вызов Directory.CreateDirectory() не завершается ошибкой, если каталог существует. Вся ваша проверка бессмысленна. - person binki; 18.05.2016
comment
@m-y Вы правы, что Directory.Exists(path) лишнее. Но как только это удалено, состояние гонки все еще остается. Фактическое состояние гонки заключается в том, что каталог может быть удален между Directory.CreateDirectory() и new DirectoryCatalog(). Хотя просто позволить приложению выйти из строя в этот момент может быть лучше, чем потенциально войти в бесконечный цикл, пытаясь воссоздать каталог, если он продолжает исчезать. Если он продолжает исчезать, у вас другая проблема — проблема со средой хостинга программы ^^. - person binki; 18.05.2016