Search code examples
.netdependency-injectioninversion-of-controlservice-locator

Getting rid of the ServiceLocator in the base class


I have an abstract base class for command/query handlers:

public abstract class AbstractBusiness<TRequest, TResult> : IBusiness<TRequest, TResult>
    where TResult : BaseResponse
{
    public TResult Send(TRequest request)
    {
        TResult response = Activator.CreateInstance<TResult>();
        response.Success = true;

        try
        {
            IConnectionProvider connectionProvider =
                ServiceLocator.Current.GetInstance<IConnectionProvider>();

            using (DatabaseScope scope = DatabaseScopeManager.Instance.GetScope(
                connectionProvider, 
                DatabaseScopeType.UseExistingOrNewTX,
                IsolationLevel.ReadCommitted))
            {
                response = this.Handle(request);
                scope.Complete();
            }
        }
        catch (Exception exc)
        {
            response.Success = false;
            response.Message = exc.Message;
        }

        return response;
    }

    protected abstract TResult Handle(TRequest request);
}

This is how it is used:

public sealed class AccountCreateBusiness
    : AbstractBusiness<AccountCreateRequest, AccountCreateResponse>
{
    private readonly IMessageProvider messageProvider;

    public AccountCreateBusiness(IMessageProvider messageProvider)
    {
        this.messageProvider = messageProvider;
    }

    protected override AccountCreateResponse Handle(AccountCreateRequest request)
    {
        //handle request
    }
}

I'm trying to get rid of the ServiceLocator in the base class. Is there a way to inject IConnectionProvider without having to change all derivative classes to include IConnectionProvider in their constructors and calling : base(connectionProvider)? I can't change DatabaseScopeManager.


Solution

  • There's an alternative: property injection.

    BTW, property injection doesn't define mandatory dependencies, while constructor dependencies do it.