Adam V. Steele
Adam V. Steele

Reputation: 639

Extending the ILogger interface

I'd like to add a method to the ILogger interface. For logger types not implementing this function I'd like them do do nothing (or use a default implementation). For those that do, their implementation should be called.

This below doesn't work. Error CS0539

public static class ILoggerExtensions
{
    // no-op default implementation
    public static void Do(this ILogger logger) { }
}
// ... then in some logger implementation
public class SpecialLogger: ILogger
{
    public void ILogger.Do()
    {
        // ...
    }
}

This below works, but is ugly.

public static class ILoggerExtensions
{
    public static void Show(this ILogger logger) 
    {
        var type = logger.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance);
        var l = logger.GetType().GetField("_logger", BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(logger);
        if (l is null) return;
        var ps = l.GetType().GetProperty("Loggers")?.GetValue(l) as IEnumerable;
        if (ps is null) return;
        foreach(var p in ps)
        {
            var specialLogger = p.GetType().GetProperty("Logger")?.GetValue(p) as SpecialLogger;
            if (specialLogger is null) continue;
            specialLogger.Do();
        }
    }
}

Upvotes: 4

Views: 4307

Answers (1)

Joel H-T
Joel H-T

Reputation: 41

You could couple generics with extending the ILogger interface to more closely approach what you're after:

public interface ISpecialLogger : ILogger
{
    void Do();
}

public static class ILoggerExtensions
{
    // explicit implementation
    public static void Do<T>(this T logger)
        where T : ISpecialLogger
    {
        logger.Do();
    }

    // no-op default implementation
    public static void Do(this ILogger logger) {
    }
}

// ... then in some logger implementation
public class SpecialLogger : ISpecialLogger, ILogger
{
    public void Do() { }
}

Upvotes: 4

Related Questions