Search code examples
c#asp.net.netdependency-injectionienumerable

How do I resolve IEnumerable of services of different types


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;
        }

Solution

  • 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();
            }
        }
    }