Using Named registrations without Service Locator

Nov 1, 2013 at 2:52 PM
I've been using Unity for a while now, but it occurs to me I've been implementing it using an anti-pattern, namely Service Locator.

Assume I've got a interface responsible for pricing merchandise. Customers pay 100% of MSRP, while employees pay 75% (contrived to be sure, but it illustrates my point).

I have an interface, IPricingPolicy and two implementations; CustomerPricingPolicy and EmployeePricingPolicy.

Since both can be valid (given the context of the purchasing user), I load both into Unity, using a named registration (container.Register<IPricingPolicy>( typeof(CustomerPricingPolicy),"Customer") and container.Register<IPricingPolicy>(typeof(EmployeePricingPolicy),"Employee").

When I need an instance of the correct policy, I get it from the container as such (psuedocode): var pricingPolicy = container.Resolve<IPricingPolicy>(customer.Role=="Employee"?"Employee":"Customer");

The problem here is that I'm hiding the dependency on an IPricingPolicy, making it challenging to write unit tests, but I obviously can't pass an instance of IPricingPolicy on the constructor, since the same instance of the code might run for both employees and customers, and Unity wouldn't know which instance to pass during instantiation.

I thought about abstracting that to a service factory pattern, IPricingPolicyFactory with an implementation for UnitTesting, and one for Runtime, but I'm not sure that level of abstraction is the correct solution (plus it means creating a service factory implementation for each interface that may have multiple runtime implementations).

Your thoughts would be greatly appreciated.
Nov 1, 2013 at 6:49 PM
Prevent complicating your DI registration with this. Create a proxy class instead that contains the logic. Here's an example:
public class PricingPolicyProxy : IPricingPolicy
    private readonly ICustomerContext context;
    private readonly IPricingPolicy customerPolicy;
    private readonly IPricingPolicy employeePolicy;

    public PricingPolicyProxy(ICustomerContext, IPricingPolicy customerPolicy, IPricingPolicy employeePolicy)
        this.context = context;
        this.customerPolicy = customerPolicy;
        this.employeePolicy = employeePolicy;

    public double CalculateDiscount()
        var policy = this.context.Customer.Role== "Employee" ? this.employeePolicy : this.customerPolicy;
        return policy.CalculateDiscount();
This class can be tested easily and registered easily as well:
container.Register<IPricingPolicy>(new InjectionFactory(c => new PricingPolicyProxy(
Nov 4, 2013 at 7:10 AM
Edited Nov 5, 2013 at 1:17 AM
@develop16 there are a lot of options available to you in this case. The key point to avoid a service locator pattern is to restrict reference of the container to the bootstrapping code and the composition root. Which approach is best might depend on the specific application/design.

@dot_NET_Junkie has shown proxy (or facade) that encapsulates the IPricingPolicy logic and determines the correct type to use at runtime.

You also mentioned creating an IPricingPolicyFactory which is another valid approach. If you didn't want to create an actual factory class you could also use Unity to provide the factory logic:
    new InjectionFactory(c =>
            var customerContext = c.Resolve<ICustomerContext>();

            if (customerContext.Customer.Role == "Employee")
                return c.Resolve<EmployeePricingPolicy>();
            else if (customerContext.Customer.Role == "Customer")
                return c.Resolve<CustomerPricingPolicy>();

            throw new Exception("Invalid Role: " + context.Customer.Role);
I'm assuming that ICustomerContext is the customer context for the current request so it would be registered with a per request lifetime or perhaps using a child container. Or if this is a web app you could drive it off of HttpContext or IPrincipal. For testing you could have separate bootstrap code for the InjectionFactory. It's a trade off between more factory classes and (more complicating) factory logic in the bootstrap code.

Another approach would be to create named registrations and then inject the appropriate IPricingPolicy by name:
container.RegisterType<IPricingPolicy, CustomerPricingPolicy>("Customer");
container.RegisterType<IPricingPolicy, EmployeePricingPolicy>("Employee");

    new InjectionConstructor(
        new ResolvedParameter<IPricingPolicy>(
            new ResolvedParameter<ICustomerContext>().Customer.Role)));

Yet another approach would be to use a dependency override in the composition root to decide on the correct version to inject. This is useful if IPricingPolicy is injected into multiple classes and you want to inject the same instance for all objects in the graph without explicitly wiring them up:
// Bootstrap
container.RegisterType<IPricingPolicy, CustomerPricingPolicy>("Customer");
container.RegisterType<IPricingPolicy, EmployeePricingPolicy>("Employee");


// ...

// Later in composition root assuming we have the context from the request
var service = container.Resolve<OrderService>(
    new DependencyOverride<IPricingPolicy>(
        new ResolvedParameter<IPricingPolicy>(context.Customer.Role)));

Randy Levy
Enterprise Library support engineer
Support How-to