Home > other >  get IEnumerable<TClass> from ServiceProvider But Create instance after use FirstOrDefault
get IEnumerable<TClass> from ServiceProvider But Create instance after use FirstOrDefault

Time:04-25

Maybe you are confused with this question, but I have problem with that. I have a class implementing an interface like this.

public class SampleA : ISample 
{
    public Guid Id  = FirstGuid;
    public SampleA()
    {
        // do some thing
    }
}
public class SampleB : ISample 
{
    public Guid Id  = SecondGuid;
    public SampleB()
    {
        // do some thing
    }
}
public class SampleC : ISample 
{
    public Guid Id  = ThirdGuid;
    public SampleC()
    {
        // do some thing
    }
}

In other class I use service provider for creating an instance of any of these classes.

public ISample GetInstance(Guid Id)
{
     return _serviceProvider.GetServices<ISample>().FirstOrDefault(d => d.Id==Id);
}

My problem is that every time I call "GetInstance" run constructor of all of classes that is very bad for me. I have one answer that add Initialize method in "ISample" and call that after call "GetInstance".

Is there anything better?

CodePudding user response:

It depends on the nature of was is really done in // do some thing.

If this work is always the same regardless of the instance created, it could be initialized once with a static constructor.

Otherwise, your intuition to add an Initialize method in ISample will guide you in the right direction. My only concern is that calling this method inside GetInstance will not change anything performance wise because you just deferred the same work from the constructor to an initialization method and will introduce a temporal coupling between the constructor and this method. That is, forgetting to call this method after the construction and the returned instance will be in a corrupted state (this is even worse than before).

If you want to fully go down the road, you need to ask yourself how to defer this complex code from the object's construction (this is considered as an anti-pattern) to a subsequent method call. But again, without seeing what is really done in the constructor and where and how the initialized part is used, I can't really say anything as how to do it.

CodePudding user response:

I think it's better to inject ISample service into your class constructor instead of get it from DI manually like this:

 public class UseDI
    {
        private readonly IEnumerable<ISample> _sampleServices;

        public UseDI(IEnumerable<ISample> sampleServices)
        {
            _sampleServices = sampleServices;
        }


        public ISample GetInstance(Guid Id)
        {
            return _sampleServices.FirstOrDefault(d => d.Id == Id);
        }
    }

By this way injection is done one time and the performance is better than get them from ServiceProvider repeatedly.

  • Related