Come posso nascondere le dipendenze dai miei servizi?

1

Ecco un'astrazione di servizio su cui sto lavorando:

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

public IQueryManager QueryManager{get;set;}

public ICommandManager  CommandManager{get;set;}
}

Quindi devo chiamarli come al solito nella mia classe:

Logger.Log("Something");

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

etc.

Ma mi piacerebbe avere alcuni metodi di supporto protetti per rendere queste frasi meno dettagliate:

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

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

Esiste un modo per implementare le mie dipendenze in modo che vengano nascoste ai figli del servizio? Esiste un contenitore IoC che mi consente di utilizzare proprietà private per iniettare le mie dipendenze?

    
posta Beatles1692 11.03.2012 - 13:20
fonte

3 risposte

4

Potresti avere un costruttore sulla tua classe base che accetta Logger e QueryManager come argomenti. In questo modo puoi mantenere i campi privati e ancora li hanno iniettati usando l'iniezione del costruttore.

vale a dire. più o meno così:

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)
   {
       ...
   }
}

Il tuo contenitore dovrebbe quindi essere in grado di risolvere MyService e iniettare le dipendenze nel costruttore.

    
risposta data 11.03.2012 - 13:31
fonte
1

L'iniezione del costruttore dovrebbe essere preferita all'iniezione di proprietà nella maggior parte dei casi ..

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());
    }
}
    
risposta data 12.03.2012 - 11:40
fonte
0

A seconda della versione del framework, è possibile creare metodi di estensione su oggetto.

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

Modifica aggiornata per riflettere il feedback di seguito. Metti il tuo nome di classe o un super tipo, o un'interfaccia implementata su cui Logger esiste dove dice YourTypeNameHere.

    
risposta data 11.03.2012 - 14:39
fonte

Leggi altre domande sui tag