2015-04-14 21 views
7

我想添加一個通用的回調函數到一個對象的所有方法。我發現this SO question,但在這個問題上,我不得不修改班級的每個功能。我想定義一些在每次方法調用之前都被觸發的beforeFilter方法。我知道我可以使用Action delegates,但我不知道如何。如何添加一個回調到webform項目

UPDATE:作爲一個例子,我想會是這樣的

Class MyClass 

    Sub MyCallback 
     'callback code... 
    End Sub 

    'Rest of tyhe code 

End Class 

正如你所看到的,理想的做法是添加一個簡單的(或多個)方法來得到trigered在所有其他方法之前。也許有一些基類或接口,我不知道(這就是爲什麼我要求)。

我認爲它可能是可行的一些其他選項是克隆該對象並定義一個新類,而不是將代碼添加到現有的代碼。因此,在這種Class使用Object以訪問trhough的Type

Class NewClass 

    Sub AddCallback(Obj As Object, Callback As Action) 
      'Add the callback here 
    End Sub 
End Class 

方法我只是猜測,也許我的一些選項甚至是不可行的,所以請幫助我對這個

最近接近

我有現在,是該方法

Sub RunWithCallback(beforFilter As Action, f As Action) 

    beforeFilter() 
    f() 

End Sub 

(這意味着RunWithCallback負責管理Sub和函數的過載很多,Action s和Func的代表具有不同數量的參數)爲了使用它,我必須運行此Sub而不是調用任何Object方法(通過ByRef參數捕獲函數中的返回值)。事情是這樣的

Public Sub DoNothing() 
    Debug.WriteLine("Callback working!") 
End Sub 

Public Sub BeforeFilter() 
    Debug.WriteLine("Testing callback...") 
End Sub 

'To run the above function  
RunWithCallback(AddressOf BeforeFilter, AddressOf DoNothing) 

我覺得應該有一個更好的解決這一點,一些允許避免調用同一子,並避免過載,某種動態擴展方法的對象類

+0

一些示例代碼可能是有用的,因爲它很不清楚你想要什麼,例如,'beforeFilter'應該在方法之前被調用被調用或在t他開始每種方法?一個'Action'委託將仍然需要重構,所以看起來並不像你想要的那樣。 – Plutonix

+0

檢查我的編輯,如果您仍有疑問,請再次評論。 –

+0

如果'MyCallback'在'MyClass'中並且從'MyClass'中調用,爲什麼類不能調用它(這不像'回調')。當一個方法*不能訪問你想從其他地方使用的方法*時,更常見的是使用一個委託(不一定是'Action')。例如,'ClassA.DoFoo'是從ClassB調用的,在'DoFoo'的過程中,您需要它調用'ClassB.GetBar'。 – Plutonix

回答

1

這裏有一個例子如何ü代表工作以及如何使用它們:

public class MyClass 
{ 
    // MyDelegate callback holder 
    private MyDelegate _myDelegate; 

    // Singleton holder 
    private static volatile MyClass _instance; 

    ///<summary> 
    /// Instance property 
    ///</summary> 
    public static MyClass Instance 
    { 
     get 
     { 
      if (_instance == null) 
      { 
       _instance = new MyClass(); 
      } 
      _instance.MyCallbacks(_instance.MyDelegateCallback, _instance.MyDelegateCallback1); 
      return _instance; 
     } 
    } 

    ///<summary> 
    /// Instance multi-callback caller 
    ///</summary> 
    ///<param name="callbacks">calbacks to call</param> 
    ///<returns>MyClass</returns> 
    public static MyClass Instance(params MyDelegate[] callbacks) 
    { 
     if (_instance == null) 
     { 
      _instance = new MyClass(); 
     } 
     _instance.MyCallbacks(callbacks); 
     return _instance; 
    } 

    ///<summary> 
    /// MyClass constructor 
    ///</summary> 
    private MyClass() 
    { 
     // Define the callback 
     MyDelegate = MyDelegateCallback; 
    } 

    ///<summary> 
    /// MyDelegate property, here u can change the callback to any function which matches the structure of MyDelegate 
    ///</summary> 
    public MyDelegate MyDelegate 
    { 
     get 
     { 
      return _myDelegate; 
     } 
     set 
     { 
      _myDelegate = value; 
     } 
    } 

    ///<summary> 
    /// Call all given callbacks 
    ///</summary> 
    ///<param name="callbacks">callbacks u want to call</param> 
    public void MyCallbacks(params MyDelegate[] callbacks) 
    { 
     if (callbacks != null) 
     { 
      foreach (MyDelegate callback in callbacks) 
      { 
       if (callback != null) 
       { 
        callback.Invoke(null); 
       } 
      } 
     } 
    } 

    ///<summary> 
    /// RunTest, if u call this method the defined callback will be raised 
    ///</summary> 
    public void RunTest() 
    { 
     if (_myDelegate != null) 
     { 
      _myDelegate.Invoke("test"); 
     } 
    } 

    ///<summary> 
    /// MyDelegateCallback, the callback we want to raise 
    ///</summary> 
    ///<param name="obj"></param> 
    private void MyDelegateCallback(object obj) 
    { 
     System.Windows.MessageBox.Show("Delegate callback called!"); 
    } 

    ///<summary> 
    /// MyDelegateCallback1, the callback we want to raise 
    ///</summary> 
    ///<param name="obj"></param> 
    private void MyDelegateCallback1(object obj) 
    { 
     System.Windows.MessageBox.Show("Delegate callback (1) called!"); 
    } 
} 

///<summary> 
/// MyDelegate, the delegate function 
///</summary> 
///<param name="obj"></param> 
public delegate void MyDelegate(object obj); 

我我的答案更新,看看MyCallbacks(params MyDelegate[] callbacks)。它會調用與MyDelegate結構相匹配的不同回調。
編輯:
添加MyClass.Instance & MyClass.Instance(params MyDelegate[] callbacks)

+0

在你的答案中,我可以看到你可以處理不同的回調結構,但是如何在其他類方法之前調用回調? –

+0

我編輯了我的答案,我添加了'MyClass.Instance'。在「get」方法中,我添加了2個測試回調函數的MyCallbacks(params MyDelegate []回調函數)。所有你必須調用一個方法的地方,就像調用MyClass.Instance.MyMethodToCall()一樣,因爲你每次調用MyClass.Instance時都會調用你定義的回調函數。 - 我認爲沒有更好的解決方案。 - 除了添加MyCallbacks(params MyDelegate []回調函數)'''''''''''''''''''''''''''''''' – k1ll3r8e

+0

第二次編輯時,我添加了附加的'MyClass.Instance(params MyDelegate []回調函數)',所以你也可以在需要的時候調用特殊的回調函數。 – k1ll3r8e

1

你有沒有考慮過使用Aspect庫?直到你的問題,似乎你真的可以用這種方法解決你的問題。

例如,你可以使用PostSharp library這裏,簡單地推導出OnMethodBoundaryAspect class,並處理四個可用的主要事件:

或兩個附加:

  • 的onResume
  • OnYield

或任何人。簡單的模式是這樣的:

int MyMethod(object arg0, int arg1) 
{ 
    OnEntry(); 
    try 
    { 
     // YOUR CODE HERE 
     OnSuccess(); 
     return returnValue; 
    } 
    catch (Exception e) 
    { 
     OnException(); 
    } 
    finally 
    { 
     OnExit(); 
    } 
} 

所以,你可以方便地調用Callback功能(你可以在OnSuccess方法提取運行時傳遞的參數:

public override void OnSuccess(MethodExecutionArgs args) 
{ 
    CallBack(GetValueYouNeed(args)); 
} 

PostSharp的簡易版是一個免費的許可分佈式和有據可查的,所以我強烈建議你去研究這個方法

+0

看起來很有希望,但它對我沒有任何作用。我繼承了上面提到的類,覆蓋了OnEntry方法,並沒有發生任何事......該方法沒有自動觸發。也許我做錯了什麼。 –

+0

我記得,你必須爲PostSharp添加一個post構建事件 – VMAtm

相關問題