1

I need to inject dependency in Startup.cs

 public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddTransient<IAppService, AppService>();
           //how to inject for the rest
        }
    }

to achieve the line below:

   new AppService(new CacheRepository(new ConfigRepository()))

instead of below or others

   new AppService(new ConfigRepository())

Decorator pattern with multiple implementation below:

public class ConfigRepository : IRepository
{    
    public async Task<IEnumerable<Data>> ReadDataAsync()
    {
      //...

    }
}


public class CacheRepository : IRepository
{
    private readonly IRepository _pository;   
    public CacheConfigRepository(IRepository repository)
    {
        _pository = repository;
    }
    public async Task<IEnumerable<Data>> ReadDataAsync()
    {
      //...

    }
}

Environment: .Net Core 2.2, Azure Functions

Update

Answer:

Thanks @Timo for providing the link below https://github.com/khellang/Scrutor

How to overwrite a scoped service with a decorated implementation?

Pingpong
  • 7,681
  • 21
  • 83
  • 209

2 Answers2

0

For decorating a service with a decorated cached service you can use the Scuter.

Example:

public class MyService : IMyService
{    
    private readonly IRepository _repository;

    public MyService(IRepository repository)
    {
         _repository = repository;
    }
    public async Task<IEnumerable<Data>> ReadDataAsync()
    {
        //...
    }
}

The decorated cache service:

public class MyCacheService : IMyService
{
    private readonly IMyService _myService;
    private readonly ICacheRepository _cacheRepository;
    public MyCacheService(IMyService myService, ICacheRepository cacheRepository)
    {
        _myService = myService;
        _cacheRepository = cacheRepository;
    }

    public async Task<IEnumerable<Data>> ReadDataAsync()
    {
        var cachedKey = "SomeKey";
        (isCached,value) = await _cacheRepository.ReadDataAsync();
        if (isCached)
            retrun value;

        var result = await _myService.ReadDataAsync();
        return result;
    }
}

Startup.cs:

services.AddSingelton<IMyService, MyService>();
services.Decorate<IMyService, MyCacheService>();

Note that in this example I've added a different interface ICacheRepository.

Shahar Shokrani
  • 7,598
  • 9
  • 48
  • 91
0

Contrary to popular belief, the decorator pattern is fairly easy to implement using the built-in container.

By using the extension methods in the linked answer, registering decorators becomes as simple as this:

public void ConfigureServices(IServiceCollection services)
{
    // First add the regular implementation
    services.AddTransient<IRepository, ConfigRepository>();
    
    // Wouldn't it be nice if we could do this...
    services.AddDecorator<IRepository>(
        (serviceProvider, wrappedRepository) => new CacheConfigRepository(wrappedRepository));
    
    // ...or even this?
    services.AddDecorator<IRepository, CacheConfigRepository>();
}
Timo
  • 7,992
  • 4
  • 49
  • 67
  • I updated my OP to reflect this. But I found the example on Scrutor is a bit different from what you provided. – Pingpong Sep 30 '20 at 11:55
  • @Pingpong Different? Ok, I haven't mentioned Scrutor nor know about it... Please elaborate. Also, the Scrutor link was provided by Shahar Shokrani. You could correct that in your mention in the OP. – Timo Oct 01 '20 at 09:03