How do I resolve IEnumerable of services of different types

Viewed 239

This is my interface:

public interface ISocialService<T> where T : ISocialModel
{
    public Task<List<T>> GetPosts();
}

I have 2 implementations of this interface. This is how I try to register them

services.AddScoped<ISocialService<RedditPost>, RedditService>();
services.AddScoped<ISocialService<HackerNewsModel>, HackerNewsService>();

And finally this is how I try to resolve them.

public ScrapeJob(IEnumerable<ISocialService<ISocialModel>> socialServices)
{
    _socialServices = socialServices;
}

However socialServices is empty. I think the problem lies in ISocialModel. Anyone got suggestions how can I register or resolve them properly?

The reason why I want to use a generic interface is I want to inject specific service into a controller like this:

public HackerNewsController(ISocialService<HackerNewsModel> socialService)
        {
            _socialService = socialService;
        }
2 Answers

The problem is you have injected generic interface IEnumerable<ISocialService<ISocialModel>> but you don't have any classes that implement ISocialService<ISocialModel> instead you have ISocialService<T> implementation in classes.
so we need to update the code following way for example

public interface ISocialModel
{

}

public class RedditModel : ISocialModel
{

}

public interface ISocialService
{
     Task<List<ISocialModel>> GetPosts();
}

public interface ISocialService<T>: ISocialService where T : ISocialModel
{
     Task<List<T>> GetPosts();
}

public abstract class SocialServiceBase<T> : ISocialService<T> where T : ISocialModel

{
    async Task<List<ISocialModel>> ISocialService.GetPosts()
    {
        var posts = await GetPosts();

        return posts.Cast<ISocialModel>().ToList();
    }

   public abstract Task<List<T>> GetPosts();
    
}

public class RedditSocialService : SocialServiceBase<RedditModel>
{
    public override Task<List<RedditModel>> GetPosts()
    {
        //TODO: past your implementation here


    }
}

so in registration now you can write following code

    services.AddScoped<ISocialService, RedditService>(); 
    services.AddScoped<ISocialService, HackerNewsService>();

and later in class you can use like that

  class ScrapeJob
{
    private IEnumerable<ISocialService> _socialServices;

    public ScrapeJob(IEnumerable<ISocialService> socialServices)
    {
        _socialServices = socialServices;
    }


    public async Task DoScrapeJob()
    {
        foreach( var service in _socialServices)
        {
           var posts = await service.GetPosts();
        }
    }
}
Related