Reputation: 639
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
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