2011-04-08 51 views
7

我想在類庫中提供對象「輸出」消息的能力,而不用擔心它如何輸出。類庫可用於控制檯應用程序,WinForm或WPF窗口應用程序或網頁。使用什麼?代表,事件或Func <T>?

我最初決定使用委託來處理這個問題。我使用類實現了這一點,但是當我試圖將委託放入每個這些對象所固有的接口時,編譯器不喜歡委託。

我發現我可以將委託移出界面,然後能夠編譯,但我不確定這會完成我想要做的事情。它也看起來像一個雜湊,所以我想問如果你們任何人有不同的想法來完成這個...

接口:

namespace Test 
{ 
    using System; 
    using System.Xml.Linq; 

    public interface IAction 
    { 
    DisplayMessageDelegate DisplayMessage(string message); 
    void Execute(); 
    XElement Serialize(XName elementName); 
    } 

    public delegate void DisplayMessageDelegate(string message); 
} 

從那裏,我不知道如何實現這一行爲:(順便說一句,我知道,這個代碼將不會編譯...)

public class ActionClass1 : IAction 
{ 
    // Other methods not shown... 
    void Execute() 
    { 
    if (this.DisplayMessage != null) 
    { 
     this.DisplayMessage(「Hello」); 
    } 
    } 
} 

public class ConsoleClass 
{ 
    ActionClass1 class1 = new ActionClass1(); 
    class1.DisplayMessage = { x => Console.WriteLine(x); }; 
} 

public class WinFormClass 
{ 
    ActionClass1 class1 = new ActionClass1(); 
    Class1.DisplayMessage = {x => DisplayTextBox.Text = x; }; 
} 

回答

11

如果您希望能夠連接多個代表以響應對Execute的單個呼叫,我肯定會使用event。如果您只想要連接一個動作,請使用ActionFunc委託人。

對於您的示例,其中一位Action代表應該工作。在你的情況下,這將是Action<string>,因爲你的委託接受一個字符串參數。 Action只是一個代表零,或多個參數,並返回void。看起來你沒有返回任何東西,所以我建議Action

如果您的委託需要返回某些內容,則只需使用Func<TResult>FuncAction之間的區別在於Func代表具有返回類型,Action代表不具有返回類型。這些委託中的任何一個都可以使用最多16個參數的泛型版本。

如果你需要一個代表超過16個參數,你可能要重新設計:)

+1

應該提到的是,如果你需要比params更復雜的任何東西,ref/out ... Action/Func不會工作。另外一個'精緻'是你可以正確命名參數(智能感知)。這是說我也會使用行動。 – Jake 2011-04-08 21:42:56

1

你的接口定義是錯誤的。你需要像這樣指定它:

namespace Test 
{ 
    using System; 
    using System.Xml.Linq; 

    public interface IAction 
    { 
    DisplayMessageDelegate DisplayMessage { get; set; }; 
    void Execute(); 
    XElement Serialize(XName elementName); 
    } 

    public delegate void DisplayMessageDelegate(string message); 
} 

然後實現接口。

4

您可以使用Action<string>來做到這一點。

您不想使用Func<T>,因爲它定義了一個不帶參數但返回T類型的單個值的委託。另一方面,Action<T>是一個委託,它接受一個類型爲T的單個參數。

我會建議嘗試:

public interface IAction 
{ 
    Action<string> DisplayMessage { get; set; } 

    void Execute(); 
    XElement Serialize(XName elementName); 
} 

一旦實現了這個接口(完全),你可以通過使用它:

public class ConsoleClass 
{ 
    public void SomeMethod() 
    { 
     ActionClass1 class1 = new ActionClass1(); 
     class1.DisplayMessage = x => Console.WriteLine(x); 
    } 
} 

或者:

public class ConsoleClass 
{ 
    public void SomeMethod() 
    { 
     ActionClass1 class1 = new ActionClass1(); 
     class1.DisplayMessage = this.Print; 
    } 

    private void Print(string message) 
    { 
     Console.WriteLine(message); 
    } 
} 

你可以這樣做事件發生的同樣的事情,但是,我會質疑這一點。您的API正在描述應該發生的操作,而不是您正在響應的事件 - 因此,我不會推薦一個事件。

1

這裏

DisplayMessageDelegate DisplayMessage(string message); 

你描述了接受字符串並返回DisplayMessageDelegate方法。 使用

event DisplayMessageDelegate DisplayMessage; 

代替。

0

個人而言,我會盡可能擁有一個抽象基類,它定義了一個名爲DisplayMessage的抽象方法,然後通過派生它來擴展該基類以改變消息顯示方式的行爲。

+0

我的確考慮過......我忽略了這個事實(試圖簡化問題),這些派生類將在List 集合中,我將執行ForEach循環來爲每個項目執行Execute方法,設置根據我在當時運行的應用程序的類型調整「DisplayMessage」... – 2011-04-09 01:58:30

0

相反的:

DisplayMessageDelegate DisplayMessage(string message); 

務必:

event Action<string> DisplayMessage; 

然後按正常使用DisplayMessage,事件委託。

相關問題