Расширение интерфейса 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() { }
}