Остановить RegisterAssemblyModules при повторном сканировании сборки, если она уже была отсканирована?

#.net #dependency-injection #autofac

#.net #внедрение зависимостей #autofac

Вопрос:

Моя ситуация:

Мне нужно сообщить Autofac builder, чтобы загрузить сборку, на которую ссылается. К этому времени она не была загружена сама по себе, и мне это нужно до того, как загрузчик завершит настройку контейнера.

 public class AppRegisterModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterAssemblyModules(typeof (IPluginManager).Assembly);
    }
}
 

Все это работает, и модуль PluginManagerRegistrationModule загружается отлично.

Сейчас меня беспокоит то, что я не могу узнать, просил ли я уже разработчика загрузить эту сборку. т. Е. Моя структура — это множество сборок с их собственными модулями регистрации, от которых они зависят. Я также вижу, что перекрестная зависимость создаст циклический цикл (хотя у меня нет перекрестных зависимостей).

В настоящее время я вижу, что это:

  builder.RegisterAssemblyModules(typeof (IPluginManager).Assembly);
 builder.RegisterAssemblyModules(typeof (IPluginManager).Assembly);
 

… запускает модули регистрации дважды, и я получаю дубликаты регистраций и дубликаты разрешенных типов (IEnumerable<> ).

Есть ли способ избежать дубликатов?

Ответ №1:

Мое решение состояло в том, чтобы предварительно загрузить все модули и сборки, прежде чем переходить к

 containerBuilder
   .RegisterAssemblyModules(
       AppDomain.CurrentDomain.GetAssemblies());
 

с

 private void PreConfigureRegistrationModules()
{
    var parsedAssemblies = new List<Assembly>()
    {
        typeof (Autofac.Core.IModule).Assembly
    };

    do
    {
        var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();

        var unparsed = loadedAssemblies
            .Where(x => parsedAssemblies.Contains(x) == false)
            .SelectMany(x => x.GetTypes())
            .Where(x => typeof (Autofac.Core.IModule).IsAssignableFrom(x))
            .Where(x => x.IsInterface == false)
            .Where(x => x.IsAbstract == false)
            .ToList();

        var unparsedAssemblies = unparsed
            .Select(x => x.Assembly)
            .Distinct()
            .ToList();

        if (unparsed.Count == 0)
            return;

        unparsed.ForEach(x => Activator.CreateInstance(x));

        parsedAssemblies.AddRange(unparsedAssemblies);

    } while (true);
}
 

Затем в любом модуле регистрации, который должен предварительно загружать ссылочные сборки перед RegisterAssemblyModules, я добавляю что-то, чтобы заставить сборку загружаться

 public class AppRegisterModule : Autofac.Module
{
    static AppRegisterModule()
    {
        if (typeof (IPluginManager).Assembly == null)
            throw new InvalidOperationException();
    }
}
 

Это не дает прямого ответа на проблему дублирования, возникающую при повторном сканировании сборки, но я обхожу ее стороной.