2012-04-26 44 views
1

我想要做的是對各種對象之一執行方法,但在方法調用之前和之後,我需要執行函數來執行各種維護任務。前後運行的函數總是相同的。該方法的返回類型和參數幾乎可以是任何東西。具有靈活簽名的C#代表

目前,我通過爲我使用的每種可能的方法簽名定義代表來做到這一點,而且這樣做的確令人感到非常尷尬。這是一個例子:

protected delegate void DelVoidString(string string1); 
protected void Execute(DelVoidString p, string string1) 
{ 
    PreInvoke(); 
    p.Invoke(string1); 
    PostInvoke(); 
} 

除了簽名之外,所有這些簽名都是相同的。所以我的問題是:有沒有更好的方法來做到這一點?只要我有一些在需要它們的方法調用之前和之後執行PreInvoke()和PostInvoke()的方法,而不必記住每一次寫出代碼,我都不會使用委託。

我對Lambda表達式只有一種模糊的認識......他們能幫我在這裏更好嗎?或者我錯過了其他驚人的東西?謝謝!

回答

4

您可以使用泛型和內置System.Action委託類型,以減少一些重複的:

protected void Execute(Action action) 
{ 
    PreInvoke(); 
    action(); 
    PostInvoke(); 
} 

protected void Execute<T>(Action<T> action, T arg) 
{ 
    PreInvoke(); 
    action(arg); 
    PostInvoke(); 
} 

protected void Execute<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2) 
{ 
    PreInvoke(); 
    action(arg1, arg2); 
    PostInvoke(); 
} 

// Additional methods for three arguments, four arguments, etc. 

要處理的返回值,使用System.Func

protected TResult Execute<TResult>(Func<TResult> func) 
{ 
    PreInvoke(); 
    TResult result = func(); 
    PostInvoke(); 
    return result; 
} 

protected TResult Execute<T, TResult>(Func<T, TResult> func, T arg) 
{ 
    PreInvoke(); 
    TResult result = func(arg); 
    PostInvoke(); 
    return result; 
} 

您可能還需要研究C#的面向方面編程(AOP)。

+0

一般動作
的一個實例肯定會有所減少的代碼。我不知道它們可能是通用的。有一些情況下返回值不是無效的,但這些情況很少。 我發現後我發現的另一個:那麼Delegate.DynamicInvoke呢?速度不是問題,那麼這可能是一種可能性嗎? – RobinHood70 2012-04-26 04:11:13

+0

我更新了我的答案來處理返回值。 Delegate.DynamicInvoke是一種可能性,但如果您傳遞了不正確的參數數目,編譯器將無法警告您。 – 2012-04-26 04:15:56

+0

謝謝,我認爲隨着你的改變,這可能是最好的選擇。 – RobinHood70 2012-04-26 04:22:04

0

提供了主題爲他人的變化已經提供 - 你可能會考慮一個通用的抽象基類,並從它繼承像這樣:

public abstract class Executable<T> 
{ 
    protected void Execute(Action<T> action, T value) 
    { 
     PreInvoke(); 
     action(); 
     PostInvoke(); 
    } 
    private void PreInvoke() { /* something */ } 
    private void PostInvoke() { /* something */ } 
} 

public MyFooExecutable : Executable<string> 
{ 
} 

這種實施關閉通用類型stringMyFooExecutable類。這將允許你有其他的子類,改變類型,而不用爲所有類型的T打開類型。根據您的前/後調用方法做什麼,你甚至可能與投入到這些擴展方法,而不是編碼到一個接口脫身:

public interface IInvocable 
{ 
    void PreInvoke(); 
    void PostInvoke(); 
} 

public class MyFooExecutable : IInvocable 
{ 
    public void PreInvoke() { /* something */ } 
    public void PostInvoke() { /* something */ } 
} 

public static class InvocableExtensions 
{ 
    public static void Execute<T>(this IInvocable self, Action<T> action, T value) 
    { 
     self.PreInvoke(); 
     action(value); 
     self.PostInvoke(); 
    } 
} 
0

,如果你需要大量的這種前/後調用機制方法,我認爲你應該考慮使用AOP工具.net像PostSharp

你可以看到Dror Helper blog或PostSharp網站使用PostSharp的OnMethodBoundaryAspectExamples