0

I created a project with .net Core 2. Now I have a List of classes from the same interface which I needed at runtime. My problem is, I can't add this classes to the servicecollection (only one interface). So I don't have access to the other services in those classes. Also I think it wouldn't solve it.

I could create a singleton/static class with my servicecollection and use the IServiceProvider to get those other services from there, but I think that isn't the best practice.

Here is an example of my problem:

public class Manager : IManager
{
   private IList<IMyService> _myService;

   public Manager()
   {
       IList<Type> types = GetIMyServiceTypes();
       foreach (Type type in types)
       {
            var instance = (IMyService)Activator.CreateInstance(type);
            _myService.Add(instance)
       }
   }

    public IList<bool> IsTrue()
    {
        return _myService
            .Select(se => se.IsTrue())
            .ToList();
    }

   public IList<Type> GetIMyServiceTypes()
   {
       var type = typeof(IMyService);
       var types = AppDomain.CurrentDomain.GetAssemblies()
           .SelectMany(s => s.GetTypes())
           .Where(p => type.IsAssignableFrom(p))
           .ToList();

        return types;
   }
}

public class ServiceType1: IMyService
{
     public bool IsTrue()
     {
      //Need Access to IServiceCollection Services
     }
}

public interface IMyService
{
    bool IsTrue();
}

public class MyController : Controller
{
    private IManager _amanager;
    public MyController(IManager manager)
    {
         _manager = manager
    }

    public IActionResult IsTrue()
    {
         IList<bool> isTrue =_manager.IsTrue();
         return new ObjectResult(isTrue);
    }
}

Is there a pattern, which I could use to solve my problem? Is there a best practice to have access to the services without using them in the constructor?

wydy
  • 173
  • 14

1 Answers1

0

I found the solution on another post in stackoverflow https://stackoverflow.com/a/44177920/5835745

But I will post my changes for other people with the same problem. I loaded the list of classes from the configuration, but it's also possible to add all classes.

        public class Manager : IManager
        {
           private IList<IMyService> _myService;
           private readonly Func<string, IService> _serviceAccessor;

           public Manager (Func<string, IService> serviceAccessor)
           {
               IList<string> authentications = new List<string> {"value1", "value2"}
               foreach (string authentication in authentications)   
               {
                    AddAuthentication(_serviceAccessor(authentication));
               }
           }

            public IList<bool> IsTrue()
            {
                return _myService
                    .Select(se => se.IsTrue())
                    .ToList();
            }
        }

    public class Startup
    {
         public void ConfigureServices(IServiceCollection services)
         {
                services.AddTransient<Value1>();
                services.AddTransient<Value2>();

                services.AddTransient(factory =>
                {
                    Func<string, IService> accesor = key =>
                    {


           switch (key)
                    {
                        case "value1":
                            return factory.GetService<Value1>();
                        case "value2":
                            return factory.GetService<Value2>();
                        default:
                            throw new KeyNotFoundException(); 
                    }
                };
                return accesor;
            });
     }
}
wydy
  • 173
  • 14