2012-03-20 73 views
2

我遇到了一些麻烦概念化什么我应该做的,方便我的类库和使用它的程序之间的通信 - 在这种情况下,Windows窗体应用程序:如何从类库沟通

// Class in library 
class foo() 
{ 
    public foo(){} 

    public doWork() 
    { 
     log("Working..."); 
    } 

    private log(string s) 
    { 
     Console.Writeline(s); 
    } 

} 

// Forms App 
class Form1() 
{ 
    public Form1() 
    { 
     foo MyFoo = new foo(); 
     MyFoo.doWork(); 
    } 
} 

由于winforms应用程序没有听到控制台,所以对foo.log()的调用什么都不显示。有没有办法动态地覆盖foo.log方法,或者可能将具有该签名的方法赋予foo对象,该对象在运行时更适合于表单应用程序?

谢谢!基于该问题

回答

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

UPDATE

麦克潘特指出已经,您可以使用委托

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

的优点代表注入

  • 很简单声明
  • 使用方法很简单
  • 可以通过变量捕获其他参数传递。

               变量捕捉见乔恩长柄水杓文章The Beauty of Closures。接口注入

  • 优点您可以很容易地通过其构造函数传递参数记录器,像在FileLogger一个文件名。由于构造函数不是接口的一部分,所以不同的记录器可以有不同的构造函数参数。

  • 您可以使用单元测试轻松测试它,您无法使用匿名lambda表达式进行测试,因为无法从单元测试访问它们。
  • 您可以在库类的单元测试中使用模拟记录器。
  • 您可以通过从现有记录器中获取新记录器来创建新的专用记录器。
  • 您可以在记录器中声明私有帮助器方法。
+1

注意:您可以在Visual Studio的输出窗口中看到WinForms程序的控制台输出。 – 2012-03-20 23:58:09

+0

我添加了一个更新比较intreface与委托注入。 – 2012-03-21 22:49:07

+0

@ ajax81:感谢您的编辑。 – 2012-06-14 18:55:43

1

编辑之前:

foo类的方法doWork()private。你不能从你的课程库之外调用它。您必须通过public方法访问它,或者使其成为public

结帐Access Modifiers

+0

Hmm..I不认为这完全是我”米试图做。也许我没有问正确的问题。基于调用程序的性质,我希望能够为名为DoWork的foo对象分配一个方法,该对象的上下文将适用于调用它的程序。这样,只要它在Foo对象内被调用,新的方法就会被使用。 – 2012-03-20 23:50:50

+0

@ ajax81我没有看到你如何调用一个外部方法,而不用将它标记为'public'。如果方法需要知道调用程序的上下文,请考虑将适当的参数作为参数传递给方法。 – 2012-03-20 23:53:38

+0

啊,我明白你的意思了。我的错字 - doWork()现在是公开的。 – 2012-03-20 23:56:44

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

嘿,谢谢你的输入。这实际上是我想我必须做的,但我不知道该怎么做。我感谢你的发布! – 2012-03-21 21:52:50