簡體   English   中英

C# 從另一個 class 調用 function

[英]C# Call function from another class

我認為我的問題最好用一個代碼片段來描述:

class A
{
    public void FunctionToBeCalled();
}
class B
{
    public void FunctionToBeCalledAfter();
}

現在,在 FunctionToBeCalledAfter() 調用之后,FunctionToBeCalled() 需要“知道”它必須被調用。 B 不能有 A 成員,但 A 可以有 B 成員。 有什么方法可以在 C# 中實現嗎?

為什么我需要這個:Class A 是 OSI 堆棧上的應用程序級別。 B 類和 C 類(之前未提及)是運輸級別。 C 調用 FunctionToBeCalledAfter,之后需要調用 FunctionToBeCalled。 但是真誠的A是更高的級別,B和C不能依賴(有成員A),我不知道如何調用FunctionToBeCalled。

我看到了兩種方法來實現這一點,一種更容易但(可以說)不那么優雅,一種更復雜但(可以說)更優雅

  1. 不太優雅的解決方案:Singleton

Singleton 模式強制在任何給定時間只能有一個 class 的實例,這似乎與您對A的描述一致(從這里開始我將調用Foo ,我將調用B Bar )。 所以讓我們實現它:

public class Foo
{
    private static Foo _instance;

    public static Foo Instance => _instance ?? (_instance = new Foo());

    // Private constructor so no one else can instantiate Foo
    private Foo() { }

    public void FunctionToBeCalled() { /* your code here */ }
}

public class Bar
{
    public void FunctionToBeCalledAfter()
    {
        // Your existing code here
        Foo.Instance.FunctionToBeCalled();
    }
}

現在,這里的問題是,如果您的需求發生變化並且您需要多個Foo ,那么實現它將是一個相當大的重構。 另一個(更大的)缺點是我們顯式引用(即依賴) Foo ,如果Bar位於無法直接引用Foo的項目/庫中,這不是很好,也是一個問題。 幸運的是,解決方案 2 解決了這些問題:

  1. 更優雅的解決方案:事件
public class Foo
{
    // We don't need Foo to be a singleton anymore
    public void FunctionToBeCalled() { /* Your code here */ }
}

public class Bar
{
    public delegate void FunctionToBeCalledAfterEventHandler();

    public event FunctionToBecalledAfterEventHandler FunctionToBeCalledAfterEvent;

    public void FunctionToBeCalledAfter()
    {
        // Your existing code here
        OnFunctionToBeCalledAfterEvent(); // Fire the event
    }

    private void OnFunctionToBeCalledAfterEvent()
    {
        FunctionToBeCalledEvent?.Invoke();
    }
}

現在,在您創建Bar實例的任何地方,您都需要引用Foo並訂閱事件,如下所示:

// foo = instance of class Foo
var bar = new Bar();

// The compiler is smart enough to find out that 'FunctionToBeCalledAfterEvent'
// has the same signature as 'FunctionToBeCalledAfterEvent' and can call it directly
// If this just so happens to not be case, see second way to subscribe to events
bar.FunctionToBeCalledAfterEvent += foo.FunctionToBeCalled;

// Or
bar.FunctionToBeCalledAfterEvent += () => foo.FunctionToBeCalled();

活動很棒

Class B 可以有其他方可以處理的事件 B.FunctionToBeCalledAfter結束時,將調用此事件。 任何注冊此活動的人都會收到通知。 通常的樣板代碼涉及一種調用一個事件的虛擬方法。 這是添加事件的標准方式。 如果事件中不需要其他數據,則使用EventArgs 如果需要其他數據,則可以將EventArgs替換為EventArgs<YourData> ,或者作為替代方案,使用這些額外數據引入從EventArgs派生的 class XxxArgs

Class B
{
    public event EventHandler FinishedFunctionToBeCalledAfter;

    protected virtual void OnFinishedFunctionToBeCalledAfter(EventArgs e)
    {
        EventHandler handler = FinishedFunctionToBeCalledAfter;
        handler?.Invoke(this, e);
    }

    public void FunctionToBeCalledAfter()
    {
        ...

        OnFinishedFunctionToBeCalledAfter(EventArgs.Empty);
    }
}

現在,當 class A 獲得 class B 的 object 時,它會將其事件處理程序添加到其中:

class A
{
    public void FunctionToBeCalled();

    public void FinishedFunctionToBeCalledAfter(object source, EventArgs e);

    public void IntroduceObject(B b)
    {
        b.FinishedFunctionToBeCalledAfter += FinishedFunctionToBeCalledAfter;
    }
}

當這個 object b的 class B應該結束其生命時 class A必須知道它,以便它可以刪除其事件處理程序:

b.FinishedFunctionToBeCalledAfter -= FinishedFunctionToBeCalledAfter;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM