Расширение интерфейса ILogger

Я хочу добавить метод в интерфейс ILogger. Для типов регистраторов, не реализующих эту функцию, я бы хотел, чтобы они ничего не делали (или использовали реализацию по умолчанию). Тем, кто это делает, следует называть их реализацию.

Это ниже не работает. Ошибка 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()
    {
        // ...
    }
}

Это ниже работает, но некрасиво.

      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();
        }
    }
}

1 ответ

Вы можете объединить дженерики с расширениемILoggerинтерфейс, чтобы более точно подойти к тому, что вам нужно:

      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() { }
}
Другие вопросы по тегам