Подтвердить что ты не робот

Как я могу регистрировать все запросы на разрешение в контейнере Autofac?

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

Нужно ли регистрировать все запросы, которые Autofac не может решить? Или, альтернативно, просто регистрируйте все запросы в контейнер?

4b9b3361

Ответ 1

Вы можете добавить журнал для запросов в контейнер, зарегистрировав специальный модуль, который будет захватывать событие Preparing для всех регистраций:

public class LogRequestsModule : Module
{
  protected override void AttachToComponentRegistration(
    IComponentRegistry componentRegistry,
    IComponentRegistration registration)
  {
    // Use the event args to log detailed info
    registration.Preparing += (sender, args) =>
      Console.WriteLine(
        "Resolving concrete type {0}",
        args.Component.Activator.LimitType);
  }
}

Это самый простой способ пойти и, вероятно, доставит вам то, что вы хотите. Сразу после того, как событие Preparing регистрирует информацию, вы увидите всплывающее исключение, и вы узнаете, какой компонент метался.

Если вы хотите получить fancier, вы можете настроить некоторые обработчики событий в контейнерах ChildLifetimeScopeBeginning, ResolveOperationBeginning, ResolveOperationEnding и CurrentScopeEnding событиях.

  • Во время ChildLifetimeScopeBeginning вам нужно настроить что-то, чтобы автоматически присоединяться к событиям жизни ResolveOperationBeginning.
  • Во время ResolveOperationBeginning вы должны зарегистрировать, что будет разрешено.
  • В течение ResolveOperationEnding вы заносили бы какие-либо исключения.
  • Во время CurrentScopeEnding вам нужно отказаться от подписки на любые события в этой области, чтобы сборщик мусора мог очистить всю область жизни всеми его экземплярами.

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

Опять же, самым простым решением является тот модуль, который я разместил выше.

Ответ 2

Просто чтобы основать отличный ответ Трэвиса, если это поможет кому-то в будущем.

Если структура вашего класса очень глубокая, может быть проще определить проблематичный путь, если вы показываете объекты в иерархии композиций. Это может быть выполнено с помощью следующих действий:

using System;
using System.Text;
using Autofac;
using Autofac.Core;

namespace Tests
{
    public class LogRequestModule : Module
    {
        public int depth = 0;

        protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry,
                                                              IComponentRegistration registration)
        {
            registration.Preparing += RegistrationOnPreparing;
            registration.Activating += RegistrationOnActivating;
            base.AttachToComponentRegistration(componentRegistry, registration);
        }

        private string GetPrefix()
        {
            return new string('-',  depth * 2);
        }

        private void RegistrationOnPreparing(object sender, PreparingEventArgs preparingEventArgs)
        {
            Console.WriteLine("{0}Resolving  {1}", GetPrefix(), preparingEventArgs.Component.Activator.LimitType);
            depth++;
        }

        private void RegistrationOnActivating(object sender, ActivatingEventArgs<object> activatingEventArgs)
        {
            depth--;    
            Console.WriteLine("{0}Activating {1}", GetPrefix(), activatingEventArgs.Component.Activator.LimitType);
        }
    }
}

Пример вывода:

--Resolving  SomeProject.Web.Integration.RestApiAdapter.RestApiAdapter
----Resolving  SomeProject.Web.Integration.RestApiAdapter.Client.ClientFactory
------Resolving  SomeProject.Web.Integration.RestApiAdapter.RestApiAdapterConfiguration
------Activating SomeProject.Web.Integration.RestApiAdapter.RestApiAdapterConfiguration
------Resolving  SomeProject.Web.Integration.RestApiAdapter.Client.Authentication.ApiClientAuthenticationService
--------Resolving  SomeProject.Web.Integration.RestApiAdapter.RestApiAdapterConfiguration
--------Activating SomeProject.Web.Integration.RestApiAdapter.RestApiAdapterConfiguration
------Activating SomeProject.Web.Integration.RestApiAdapter.Client.Authentication.ApiClientAuthenticationService