Search code examples
c#inversion-of-controlfactoryservice-locator

Factory pattern without service locator


I am currently stuck at trying to write a factory class that doesn't rely on service location.

The only other alternative I can think of is to use constructor injection to inject all possible instances, but that may lead to surprises as classes are passed via reference. It is also possibly going to be costly and messy once the number of possible providers grow.

The providers themselves are full complex classes that have their own dependencies so manual construction is out of the picture.

Updated service location example:

    public class ProviderFactory : IProviderFactory
    {
        private readonly IProviderConfigurationService _providerConfigurationService;

        public enum SearchType
        {
            Foo,
            Bar
        }

        public ProviderFactory(IProviderConfigurationService providerConfigurationService)
        {
            _providerConfigurationService = providerConfigurationService;
        }

        public Collection<IProvider> GetProviderInstances(SearchType searchType)
        {
            // Provider configuration service will read a XML/DB store to retrieve list of search providers applicable for a search type
            var providerList = _providerConfigurationService.GetProviderList(searchType);
            return new Collection<IProvider>(providerList.ForEach(x=> ServiceLocator.GetInstance(typeof(x))).ToList()) ;
        }
    }

What are my other options? I am currently using Unity for DI.


Solution

  • An alternative is to pass a Func<Type, object> to the constructor and to implement the function through your container:

    unity.RegisterInstance<Func<Type, object>>(t => unity.Resolve(t))
    

    Then in your class:

    public ProviderFactory(Func<Type, object> createFunc, IProviderConfigurationService pcs)
    {
        _createFunc = createFunc; 
    }
    
    public Collection<IProvider> GetProviderInstances(SearchType searchType)
    {
        var providerList = _providerConfigurationService.GetProviderList(searchType);
        return new Collection<IProvider>(providerList.Select(_createFunc).ToList());
    }