Как переопределить и интерфейс и вызвать «базовый» интерфейс в ASP.NET Основной встроенный контейнер DI?

#c# #asp.net-core #.net-core #dependency-injection

Вопрос:

Предположим, у меня есть интерфейс, зарегистрированный библиотекой 3pty в контейнере по умолчанию

 // 3pty lib
public interface IFoo {
  SayHello();
  SayBye();
}

internal sealed class FooInternal : IFoo { ... }

public static WithFoo(this IServiceCollection serviceCollection) { 
  serviceCollection.AddScoped<IFoo, FooInternal>();
}
 

И я действительно хочу перезаписать SayBye() метод. Я создал класс

 class FooProxy : IFoo {
   private readonly IFoo baseFoo;
   public FooProxy(IFoo baseFoo) {
     this.baseFoo = baseFoo;
   }

   public void SayHello() { baseFoo.SayHello(); }
   public void SayBye() { ... }
}
 

Теперь проблема, с которой я сталкиваюсь, заключается в том, как подключить его к инъекции зависимостей.
Я пытался:

 // leads to infinite recursion death
services.AddScoped<IFoo>((sp) => new FooProxy(sp.GetRequiredService<IFoo>()));
 

А также:

 public class FooProxy : IFoo {
  private readonly Func<IFoo> baseFoo;
  SayHello() { baseFoo().SayHello(); }
}

// leads to object disposed error 
services.AddScoped<IFoo>((sp) => new FooProxy(() => sp.GetRequiredService<IFoo>()));
 

Комментарии:

1. чего вы пытаетесь достичь ? то, как вы реализовали FooProxy, на самом деле является бесконечной рекурсией

2. @EhsanSajjad — это не так ? У меня есть библиотека 3pty, которая помещает интерфейс в контейнер / в моем коде, я действительно хочу в некоторых случаях вызывать этот интерфейс.

3. Вы FooProxy -декоратор, чего трудно добиться с помощью мисс ДИ из коробки.

Ответ №1:

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

Для этого есть одна библиотека.

  • https://github.com/khellang/Scrutor
     service.AddScoped<IFoo,FooConcrete>(); // This I believe register by Third Party
    
    service.Decorate<IFoo,FooProxy>(); // This is you will add.
     
  • Еще один способ, который немного нехорош.
     public interface IFooProxy: IFoo
    {
    
    }
    
    public class FooProxy : IFooProxy
    {
            public FooProxy(IFoo foo)
          {
          }
    }
    
      // Configure Sevices
      services.AddScoped<IFooProxy,FooProxy>();