Типы регистров autofac из сборки

Я использую autofac в своем решении для разрешения зависимостей библиотек в разных проектах. Идея состоит в том, чтобы сделать библиотеки горячего подключения в том смысле, что существует всего несколько основных библиотек, от которых зависит приложение, они имеют префикс "vmecore.*.dll". Который должен быть зарегистрирован с помощью autofac перед любыми другими библиотеками.

Загружается любая другая библиотека с префиксом «vme. *. Dll», затем я ищу первый тип, реализующий «IVmeExtension», определяющий метод Положить начало(), регистрирую его, активирую и, наконец, инициализирую.

Код, выполняющий регистрацию основных библиотек:

        Directory.GetFiles(path, "vmecore.*.dll")
            .Select(Assembly.LoadFile)
            .ToList()
            .ForEach(ass =>
            {
                //var validAss = Assembly.Load(ass.FullName);

                builder.RegisterAssemblyTypes(ass)
                    .Where(t => t.IsAssignableTo<IVmeExtension>())
                    .SingleInstance();
                //return;

                // Iterate through all the types in the assembly
                foreach (var type in ass.GetExportedTypes()
                        .Where(a => a.IsClass &&
                                    !a.IsAbstract &&
                                    a.Namespace != null &&
                                    a.Namespace.Contains(@"VME")))
                {
                    // Get the first type of IVmeExtension
                    if (!typeof(IVmeExtension).IsAssignableFrom(type)) continue;

                    //builder.RegisterType(type).SingleInstance();
                    coreExtension.Add(type);
                    break;
                }
            });

Приведенный ниже фрагмент - это делегат обратного вызова, который вызывается при создании контейнера. Базовые библиотеки должны быть разрешены и инициализированы перед горячим подключением расширений, поскольку от них зависит большинство расширений.

           //Register a call back when container is built so we can resolve core extensions first
            builder.RegisterBuildCallback(container =>
            {
                coreExtension.ForEach(ext =>
                {
                    try
                    {
                        var inst = (IVmeExtension)container.Resolve(ext);
                        inst.Initiate();

                        Interface.LogInfo($"VME: Core extension '{inst.Name}'");
                    }
                    catch (Exception e)
                    {
                        // we log the error here.
                        throw;
                    }
                });
            });

Второе разрешенное расширение требует, чтобы первое было внедрено в конструктор - для этого эксперимента я вручную разрешил его в конструкторе, чтобы увидеть зарегистрированные службы-. Проблема возникает здесь; Я получаю исключение «Запрошенная услуга '..' не зарегистрирована», но глядя на регистрацию, тип там литературный.

Скриншот

Я пробовал решение, предложенное в этом посте https://github.com/autofac/Autofac/issues/593, но когда я это делаю, я получаю исключение системного указателя, и это очень ясно, поскольку при активации экземпляра (var inst = (IVmeExtension)container.Resolve(ext)) среда IDE фактически переводит меня к конструктору совершенно другого class - другой класс находится в исполняющей сборке -

Эти расширения, вероятно, должны инициализироваться из конструктора (и принимать их зависимости, если таковые имеются) - есть ли причина, по которой вы должны сделать это особым случаем с дополнительным вызовом инициализации? Также - RegisterAssemblyTypes гарантирует, что это только конкретные классы - поэтому не должно быть причин проверять абстрактные и тому подобное. ToList тоже кажется лишним. Можете ли вы предоставить MVCE?

Dennis Kuypers 10.08.2018 03:03
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
1 108
1

Ответы 1

После некоторого времени, по-настоящему покопавшись, я упростил загрузку файлов в это:

        var path = "C:\\rust server\\RustDedicated_Data\\Managed";
        var coreFiles = Directory.GetFiles(path, "vmecore.*.dll");

        var coreExtension = new List<Type>();
        // Load each assembly into domain
        foreach (var file in coreFiles)
        {
            var lAssembly = Assembly.LoadFile(file);
            var assembly = Assembly.Load(lAssembly.FullName);

            builder.RegisterAssemblyTypes(assembly)
                .Where(t => t.IsAssignableTo<IVmeExtension>())
                .SingleInstance();

            // Add all IVmeExtension types
            coreExtension.AddRange(assembly.GetExportedTypes()
                .Where(a => a.IsClass &&
                            !a.IsAbstract &&
                            a.Namespace != null &&
                            a.Namespace.Contains(@"VME") &&
                            typeof(IVmeExtension).IsAssignableFrom(a)));
        }

Причина, по которой моя исходная версия не работала, заключалась в том, что, хотя сборка файла была загружена, она не была загружена в домен приложения, поэтому, когда я зарегистрировал тип, он получал хэш-код, который использует autofac. Когда приложение пыталось разрешить тип, в этот момент оно загружало сборку в домен приложения. На этом этапе все вновь загруженные типы имеют разные хэш-коды - я предполагаю, что это именно то, что происходило -, что привело к описанной мной ошибке.

Как ни странно, исключение недопустимого указателя, о котором я упоминал, на самом деле возникло, когда второе расширение было активировано и правильно разрешило его зависимости, одно из которых открыло сокет tcp с неправильно набранным IP-адресом (уурхх, коллеги, ага)

Иногда более простой код - лучший код :)

Другие вопросы по теме