Я получаю StackoverflowException в моей реализации шаблона декоратора при использовании инъекции зависимостей. Я думаю, что это потому, что я "пропускаю" что-то из своего понимания DI/IoC.
Например, в настоящее время у меня есть CustomerService и CustomerServiceLoggingDecorator. Оба класса реализуют ICustomerService, и весь класс декоратора делает это с помощью вложенного ICustomerService, но добавляет несколько простых журналов NLog, поэтому я могу использовать ведение журнала, не затрагивая код в CustomerService, а также не нарушая принцип единой ответственности.
Однако проблема заключается в том, что, поскольку CustomerServiceLoggingDecorator реализует ICustomerService, и ему также нужна реализация ICustomerService, введенная в нее для работы, Unity будет пытаться разрешить ее обратно к себе, что вызывает бесконечный цикл до тех пор, пока он переполняет стек.
Это мои услуги:
public interface ICustomerService
{
    IEnumerable<Customer> GetAllCustomers();
}
public class CustomerService : ICustomerService
{
    private readonly IGenericRepository<Customer> _customerRepository;
    public CustomerService(IGenericRepository<Customer> customerRepository)
    {
        if (customerRepository == null)
        {
            throw new ArgumentNullException(nameof(customerRepository));
        }
        _customerRepository = customerRepository;
    }
    public IEnumerable<Customer> GetAllCustomers()
    {
        return _customerRepository.SelectAll();
    }
}
public class CustomerServiceLoggingDecorator : ICustomerService
{
    private readonly ICustomerService _customerService;
    private readonly ILogger _log = LogManager.GetCurrentClassLogger();
    public CustomerServiceLoggingDecorator(ICustomerService customerService)
    {
        _customerService = customerService;
    }
    public IEnumerable<Customer> GetAllCustomers()
    {
        var stopwatch = Stopwatch.StartNew();
        var result =  _customerService.GetAllCustomers();
        stopwatch.Stop();
        _log.Trace("Querying for all customers took: {0}ms", stopwatch.Elapsed.TotalMilliseconds);
        return result;
    }
}
В настоящее время у меня установлены настройки регистрации (этот метод заглушки был создан Unity.Mvc):
        public static void RegisterTypes(IUnityContainer container)
        {
            // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
            // container.LoadConfiguration();
            // TODO: Register your types here
            // container.RegisterType<IProductRepository, ProductRepository>();
            // Register the database context
            container.RegisterType<DbContext, CustomerDbContext>();
            // Register the repositories
            container.RegisterType<IGenericRepository<Customer>, GenericRepository<Customer>>();
            // Register the services
            // Register logging decorators
            // This way "works"*
            container.RegisterType<ICustomerService, CustomerServiceLoggingDecorator>(
            new InjectionConstructor(
                new CustomerService(
                    new GenericRepository<Customer>(
                        new CustomerDbContext()))));
            // This way seems more natural for DI but overflows the stack
            container.RegisterType<ICustomerService, CustomerServiceLoggingDecorator>();
        }
Итак, теперь я не уверен в правильном способе создания декоратора с инъекцией зависимости. Я основал свой декоратор на Mark Seemann, отвечая здесь. В его примере он создает несколько объектов, которые передаются в класс. Вот как мой "работает" * работает фрагмент. Однако, я думаю, что я пропустил фундаментальный шаг.
Почему вручную создавать новые объекты, подобные этому? Разве это не отрицает того, что контейнер для меня разрешает? Или я должен вместо этого contain.Resolve() (локатор сервисов) в рамках этого одного метода, чтобы все вложенные зависимости все еще были?
Я немного знаком с концепцией "составной корень", в которой вы должны подключать эти зависимости в одном и только одном месте, которое затем каскадируется до нижних уровней приложения. Итак, Unity.Mvc сгенерированный RegisterTypes() корень композиции приложения ASP.NET MVC? Если это так, правильно ли здесь быть непосредственно новыми объектами?
У меня создалось впечатление, что, как правило, с Unity вам нужно создать собственный корневой состав, однако Unity.Mvc является исключением из этого в том, что он создает свой собственный корневой состав, поскольку он, похоже, способен вводить зависимости в контроллеры которые имеют интерфейс, такой как ICustomerService в конструкторе, без того, что я пишу код, чтобы сделать это.
  Вопрос. Я считаю, что мне не хватает ключевой информации, которая приводит меня к StackoverflowExceptions из-за круговых зависимостей. Как я правильно реализую свой класс декоратора, все еще следуя за зависимостями впрыска/инверсии принципов и соглашений управления?
  Второй вопрос: А если я решил, что я только хотел применить декоратор журнала в определенных обстоятельствах? Поэтому, если у меня было MyController1, что я хотел иметь зависимость CustomerServiceLoggingDecorator, но MyController2 нужен только обычный CustomerService, как мне создать две отдельные регистрации? Потому что, если я это сделаю:
container.RegisterType<ICustomerService, CustomerServiceLoggingDecorator>();
container.RegisterType<ICustomerService, CustomerService>();
Затем будет перезаписано значение, означающее, что оба контроллера будут либо снабжены инжектором декоратора, либо обычной инъекцией. Как мне разрешить оба?
Изменить: это не дублирующий вопрос, потому что у меня возникают проблемы с круговыми зависимостями и недостаточным пониманием правильного подхода DI для этого. Мой вопрос относится ко всей концепции, а не только шаблон декоратора, как связанный вопрос.