Iniciar sesión como decorador frente a inyección de dependencia: ¿qué sucede si necesito iniciar sesión dentro de la clase?

(Originalmente hice esta pregunta eneste comentario, pero Mark Seemann me pidió que creara una nueva pregunta).

Estoy comenzando una nueva aplicación (.NET Core, si eso es importante), y ahora estoy tratando de decidir cómo hacer exactamente el registro.

El consenso general parece ser que el registro es una preocupación transversal, por lo que el registrador no debe inyectarse directamente en la clase que se supone que debe registrar.

A menudo, hay un ejemplo como la siguiente clase de cómono para hacerlo:

public class BadExample : IExample
{
    private readonly ILogger logger;

    public BadExample(ILogger logger)
    {
        this.logger = logger;
    }

    public void DoStuff()
    {
        try
        {
            // do the important stuff here
        }
        catch (Exception e)
        {
            this.logger.Error(e.ToString());
        }
    }
}

En cambio, la clase con la lógica de negocios no debería saber sobre el registrador (SRP) y debería haber una clase separada que haga el registro:

public class BetterExample : IExample
{
    public void DoStuff()
    {
        // do the important stuff here
    }
}

public class LoggingBetterExample : IExample
{
    private readonly IExample betterExample;
    private readonly ILogger logger;

    public LoggingBetterExample(IExample betterExample, ILogger logger)
    {
        this.betterExample = betterExample;
        this.logger = logger;
    }

    public void DoStuff()
    {
        try
        {
            this.betterExample.DoStuff();
        }
        catch (Exception e)
        {
            this.logger.Error(e.ToString());
        }
    }
}

Cada vez que unIExample es necesario, el contenedor DI devuelve una instancia deLoggingBetterExample, que utilizaBetterExample (que contiene la lógica comercial real) debajo del capó.

Algunas fuentes para este enfoque:

Publicaciones de blog deMark Seemann:

Instrumentación con decoradores e interceptores.La inyección de dependencia es un acoplamiento flojo

Publicación de blog y respuesta SO porSteven:

Mientras tanto ... en el lado del comando de mi arquitecturaWindsor - sacando objetos transitorios del contenedorMi pregunta:

Obviamente, elLoggingBetterExample el enfoque solo funciona siempre que el registro se pueda realizar fuera de la clase real.
(como en el ejemplo anterior: captura las excepciones lanzadas porBetterExample desde afuera)

Mi problema es que me gustaría registrar otras cosas dentro de la clase real.
Mark Seemannsospechado aquí que si alguien necesita hacer esto, tal vez el método en cuestión también lo esté haciendo demasiado.

Como dije antes, estoy en la fase de planificación para una nueva aplicación, así que no tengo mucho código para mostrar, pero el caso de uso que estoy pensando ahora es algo como esto:

Mi aplicación tendrá un archivo de configuración con algunos valores opcionales.
El usuario puede decidir omitir los valores opcionales, pero es una decisión importante hacer esto.
Por lo tanto, me gustaría registrar una advertencia cuando faltan algunos de los valores opcionales, en caso de que ocurriera por error.
(omitir los valores está perfectamente bien, así que no puedo lanzar una excepción y detenerme)

Esto significa que tendré una clase que lee los valores de configuración y necesita hacer algo como esto (pseudocódigo):

var config = ReadConfigValues("path/to/config.file");

if (config.OptionalValue == null)
{
    logger.Warn("Optional value not set!");
}

No importa siReadConfigValues está en esta clase o en una diferente, no creo que esta clase viole el SRP.

Cuando no puedo iniciar sesión fuera de la clase real utilizando un decorador, ¿hay una mejor solución que inyectar el registrador?

Sé que podría leer el archivo de configuración en la clase interna, pero verifique los valores (y registre la advertencia) en el decorador. Pero la OMI que verifica el valor es lógica empresarial y no infraestructura, por lo que para mí pertenece a la misma clase donde se lee el archivo de configuración.

Respuestas a la pregunta(1)

Su respuesta a la pregunta