Внедрить зависимость в конструктор без параметров (контейнер Windsor)

Я хочу использовать свой дочерний класс следующим образом:

throw new MyCustomException()

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

throw new MyCustomException(correlationID)

но я не знаю, как это сделать в ситуации, когда это нужно сделать с помощью внедрения конструктора.

Другими словами, я хочу внедрить зависимость в конструктор без параметров. Что-то такое

class MyBaseException()
{
    private IWorkingContext workingContext;
    public MyBaseException()
    {
        this.workingContext = workingContext;
    }
}

И да, я знаю, что обычно мне нужно сделать это так:

public MyBaseException(IWorkingContext workingContext)

Но я хочу, чтобы этот конструктор MyBaseException(IWorkingContext workingContext) вызывался без параметров, поэтому, в конце концов, я мог бы использовать свой дочерний класс, такой как MyCustomException(), и завернуть в него рабочий контекст.

Моя регистрация в Виндзоре:

container.Register(Component.For<IWorkingContext>().ImplementedBy<WorkingContext>().LifeStyle.PerWebRequest)

Я пробовал этот подход:

var containerAccessor = HttpContext.Current.ApplicationInstance as IContainerAccessor;
var container = containerAccessor.Container;
var operationContext = container.Resolve<IWorkingContext>();

но это не работает (новый объект создается Виндзором).


person user3311556    schedule 30.11.2017    source источник


Ответы (1)


В тот момент, когда вы new создаете исключение - или любой другой класс, если на то пошло - он не управляется вашим контейнером IOC, поэтому он просто не может помочь вам обогатить ваш класс исключений.

Однако есть несколько вещей, которые вы можете сделать, некоторые из них сомнительного качества:

  1. Используйте шаблон локатора службы в конструкторе вашего исключения (очень противно)
  2. Используйте фабричный метод/класс, зарегистрированный в вашем контейнере IOC с зависимостью от IWorkingContext, который фактически даст вам экземпляр вашего исключения для создания стека. Это по-прежнему означает, что у вашего исключения будет конструктор, принимающий зависимость, но класс, выбрасывающий исключение, не знает или не должен знать об этом. (Я бы рекомендовал этот подход)

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

    • An incorrect implementation will have you lose the context of the exception (stack trace information mainly)
    • Теперь вы в значительной степени заставляете каждый компонент игнорировать исключения, поскольку вам отчаянно нужен этот контекст для исключений для целей ведения журнала или чего-то еще.
  4. Подвергните сомнению весь подход, к которому вы стремитесь. Почему бы не обогатить исключения во время регистрации контекстом вместо того, чтобы добавлять эти метаданные во время исключения?

Лично я бы рассматривал 2 как наиболее жизнеспособный вариант, но он может быстро выйти из-под контроля, если в вашем приложении есть много различных пользовательских исключений. Я бы всегда смотрел на 4, независимо от того, какой вариант вы выберете, потому что иногда проблема, которую вы пытаетесь решить, является неправильной проблемой.

person Yannick Meeus    schedule 13.12.2017