我在概念化我应该做些什么以帮助我的类库和使用它的程序之间进行通信时遇到了一些麻烦 - 在这种情况下,Windows Forms应用程序:
// Class in library
class Foo()
{
public Foo(){}
public void DoWork()
{
log("Working...");
}
private void log( string s )
{
Console.Writeline(s);
}
}
// Forms App
class Form1()
{
public Form1()
{
Foo MyFoo = new Foo();
MyFoo.DoWork();
}
}
由于在winforms应用程序中没有任何内容监听控制台,因此对log()的调用不会显示任何内容。有没有办法动态覆盖Foo.Log方法,或者可能将具有该签名的方法分配给更适合运行时表单应用程序的Foo对象?
谢谢!
答案 0 :(得分:9)
声明一个记录器接口并将具体记录器注入库类
public interface ILogger
{
void Log(string message);
}
public class Foo
{
private ILogger _logger;
public Foo (ILogger logger)
{
_logger = logger;
}
public void DoWork ()
{
_logger.Log("Working...");
}
}
像这样使用
var foo = new Foo(new ConsoleLogger());
var foo = new Foo(new FileLogger());
var foo = new Foo(new MsgBoxLogger());
所有这些记录器都实现了接口。
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
}
更新
正如迈克潘特已经指出的那样,你可以使用代表
public class Foo
{
private Action<string> _writeLog;
public Foo (Action<string> writeLog)
{
_writeLog = writeLog;
}
public void DoWork ()
{
_writeLog("Working...");
}
}
你可以这样称呼它
var foo = new Foo(s => Console.WriteLine(s));
委托注射的优点
请参阅Jon Skeets文章The Beauty of Closures了解变量捕获。
界面注入的优点
答案 1 :(得分:1)
答案 2 :(得分:1)
或者,声明一个委托函数,并让调用者将其设置为适合上下文的内容,如下所示:
public class Foo
{
public delegate void Log(string s);
public Log LoggingDelegate;
public void DoWork()
{
LoggingDelegate("Working...");
}
}
class Program
{
private static void Log( string s )
{
Console.WriteLine(s);
}
static void Main(string[] args)
{
var myFoo = new Foo();
myFoo.LoggingDelegate = Log;
myFoo.DoWork();
}
}