首先,我会质疑在这种情况下是否需要流畅的界面,似乎您可以使用更简单的界面轻松完成:
Logger.Debug.Message("Test");
甚至只是:
Logger.Debug("Test");
但是,如果您真的需要/想要一个流畅的接口,另一种方法是让流畅的接口在方法的参数上工作,而不是在返回值上工作。
所以不要这样做:
Method1().Method2().Method3();
然后忘记了最后的电话:
Method1().Method2().Method3().Execute();
您将改为组织代码,可能像这样:
Method1(o => o.Method2().Method3());
为此,您将定义一个对象,您将在该对象上调用所有流畅的方法:
public class LoggerOptions
{
public LoggerOptions Debug() { LoggerType = LoggerType.Debug; return this; }
public LoggerOptions Error() { LoggerType = LoggerType.Error; return this; }
public LoggerOptions Message(string message) { ...; return this; }
public LoggerType Type { get; set; }
...
}
这里的每个方法调用都会修改 LoggerOptions 对象,然后返回相同的实例,以继续流畅的接口。
进而:
public static class Logger
{
public static void Log(Func<LoggerOptions, LoggerOptions> options)
{
LoggerOptions opts = options(new LoggerOptions());
// do the logging, using properties/values from opts to guide you
}
}
然后你会这样称呼它:
Logger.Log(opts => opts.Debug().Message("Debug message"));
如果您在完成设置选项对象之前绝对需要调用一些终端方法,则可以创建不同的对象:
public class LoggerOptions
{
public LoggerOptions Debug() { LoggerType = LoggerType.Debug; return this; }
public LoggerOptions Error() { LoggerType = LoggerType.Error; return this; }
public LoggerOptions Message(string message) { ...; return this; }
public LoggerType Type { get; set; }
...
public LoggerFinalOptions ToEventLog() { ...; return new LoggerFinalOptions(this); }
public LoggerFinalOptions ToFile(string fileName) { ...; return new LoggerFinalOptions(this); }
}
进而:
public static class Logger
{
public static void Log(Func<LoggerOptions, LoggerFinalOptions> options)
{
LoggerFinalOptions opts = options(new LoggerOptions());
// do the logging, using properties/values from opts to guide you
}
}
这将保证如果不通过调用返回显式最终选项对象的方法来结束方法链,则无法编译代码:
// will not compile
Logger.Log(opts => opts.Debug().Message("Test"));
// will compile
Logger.Log(opts => opts.Debug().Message("Test").ToFile("log.log"));