views:

137

answers:

2

Trying to figure out how to best handle the following scenario:

Assume a RequestContext class which has a dependency to an external service, such as:

public class RequestContext : IRequestContext
{
    private readonly ServiceFactory<IWeatherService> _weatherService;

    public RequestContext(ServiceFactory<IWeatherService> weatherService, UserLocation location, string query)
    {
       _weatherService = weatherService;
       ...

What sort of dependency should I require in the class that will ultimately instantiate RequestContext? It could be ServiceFactory<IWeatherService>, but that doesn't seem right, or I could create an IRequestContextFactory for it along the lines of:

public class RequestContextFactory : IRequestContextFactory
{
    private readonly ServiceFactory<IWeatherService> _weatherService;

    public RequestContextFactory(ServiceFactory<IWeatherService> weatherService)
    {
        _weatherService = weatherService;
    }

    public RequestContext Create(UserLocation location, string query)
    {
        return new RequestContext(_weatherService, location, query);
    }
}

And then pass the IRequestContextFactory through constructor injection.

This seems like a good way to do it, but the problem with this approach is that I think it hinders discoverability (devs must know about the factory and implement it, which is not really apparent).

Is there a better/more discoverable way that I'm missing?

+3  A: 

The beauty of loose coupling is that we can constantly hide away the previous details.

From the perspective of a consumer of IRequestContext the existence of RequestContext and its dependencies is purely an implementation detail. Because of the Liskov Substitution Principle, the consumer must only deal with IRequestContext:

public class MyClass
{
    private readonly IRequestContext reqCtx;

    public MyClass(IRequestContext reqCtx)
    {
        if (reqCtx == null)
        {
            throw new ArgumentNullException("reqCtx");
        }

        this.reqCtx = reqCtx;
    }

    // Implement using this.reqCtx...
}

Only at the application's Composition Root do you need to finally wire everything together. Here's a sketch of a Poor Man's DI approach:

ServiceFactory<IWeatherService> weatherService =
    new ServiceFactory<IWeatherService>();
UserLocation location = new UserLocation;
string query = "foo";

IRequestContext reqCtx = new RequestContext(weatherService, location, query);

var mc = new MyClass(reqCtx);
Mark Seemann
Interesting, I haven't thought about injecting RequestContext directly because its parameters would vary on every page request (ASP.NET MVC). Would it be a good idea to use NInject to properly instantiate the class for me by peeking into the query string for instance? Or would I configure NInject to use a factory which returns an instance, but at the basic level just inject RequestContext?
legenden
I don't yet know Ninject well enough to answer the specifics about this, but if it doesn't support this directly, you can always implement this little part yourself using an Abstract Factory injected into a higher-level consumer.
Mark Seemann
A: 

The Factory pattern is a well known, documented, and used method. If you're that concerned about other devs not being up-to-speed, then put a link to wikipedia's factory pattern page in the (xml) documentation in the code.

Also, make sure you name your Factories consisently - Microsoft seem to like the Provider suffix.

David Kemp
+1 for "Provider" suffix. Need to refactor my factories. :)
legenden
-1 for 'Provider'. do you know _why_ they are suffixed 'Provider'? dont blindly adopt it just because MS use it. it may be for a completely different reason.
Steve
http://msdn.microsoft.com/en-us/library/ms972319.aspx indicates they use Provider to indicate a class extending ProviderBase that uses the ASP.NET Provider model. Only under those circumstances would the provider suffix be appropriate.
Steve