Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Here's a service abstraction that I am working on :

public abstract class Service
{
public ILogger Logger{get;set;}

public IQueryManager QueryManager{get;set;}

public ICommandManager  CommandManager{get;set;}
}

Then I have to call them in my class as usual :

Logger.Log("Something");

QueryManager.Query(new QueryObject()).Result;

etc.

But I'd like to have some protected helper methods to make these sentences less verbose :

Log("Something");\\calls Logger.Log("Something")

Query(new QueryObject()); \\ returns QueryManager(new QueryObject()).Result

Is there a way so that I can implement my dependencies so that they will be hidden from children of Service ? Is there an IoC container that allows me to use private properties to inject my dependencies ?

share|improve this question
add comment

3 Answers

You could have a constructor on your base class that takes the Logger and QueryManager as arguments. That way you can keep the fields private and still have them injected using constructor injection.

I.e. more or less like so:

public abstract class Service
{
    private ILogger logger;
    private IQueryManager queryManager;
    private ICommandManager commandManager;

    protected Service(ILogger logger, IQueryManager queryManager, ICommandManager commandManager)
    {
        this.logger = logger;
        // and so on..
    }
}


public class MyService : Service
{ 
    public Service(ILogger logger, IQueryManager queryManager, ICommandManager commandManager)
        : base(logger, queryManager, commandManager)
   {
       ...
   }
}

Your container should then be able to resolve MyService, and inject the dependencies into the constructor.

share|improve this answer
add comment

Constructor injection should be preferred over property injection in most cases..

public abstract class ServiceBase
{
    // Use constructor injection to get the dependencies, but they are not exposed to derived classes...
    protected ServiceBase(ILogger logger, IQueryManager queryManager, ICommandManager commandManager)
    {
        this.Logger         = logger;
        this.QueryManager   = queryManager;
        this.CommandManager = commandManager;
    }

    private readonly ILogger Logger;
    private readonly IQueryManager QueryManager;
    private readonly ICommandManager CommandManager;

    protected void Log(String message)
    {
        this.Logger.Log(message);
    }

    protected QueryResult Query(IQueryObject queryObject)
    {
        return this.QueryManager.Query(queryObject);
    }
}

public class MyService : ServiceBase
{
    // Dependencies must still be declared in the derived constructor, even though they are not exposed to this class...
    public MyService(ILogger logger, IQueryManager queryManager, ICommandManager commandManager)
        : base(logger, queryManager, commandManager)
    {
    }

    public void Foo()
    {
        Log("hello, is this foo");

        var result = Query(new QueryObejct());
    }
}
share|improve this answer
add comment

Depending on the version of the framework, you can create extension methods on object.

public static void Log(this YourTypeNameHere current, string message)
{
    current.Logger.Log(message);
}

Edit updated to reflect feedback below. Put your class name or a super type, or an interface it implements on which Logger exists where it says YourTypeNameHere.

share|improve this answer
    
You might have to switch things around a bit. I can't tell if you use Service as the service container, or if it then injects those into your current object. If it's the former, change "current.Logger.Log" to "Services.Logger.Log". –  Ian Mar 11 '12 at 13:41
    
This wont compile as-is. Logger is not a member of System.Object. This would most likely have to be a generic extension method where T is constrained to some interface which the services all implement. –  MattDavey Mar 11 '12 at 15:14
    
It doesn't have to be generic or constrained, it's a simple extension method. object would be replaced with what ever type or supertype he chooses, but that wasn't specified in the original question, so... –  Ian Mar 12 '12 at 14:55
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.