2012-03-20 74 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