2016-05-27 43 views
1

所以我有一個擴展方法,允許我在執行操作時記錄一些內容。實現是像這樣:有沒有辦法來推廣行動和行動<T>?

public static Action Log(this Action action, string log) { 
    return (() => { 
     Console.WriteLine(log); 
     action(); 

    }); 
} 

但我想允許的動作也是一個Action<T>。有沒有辦法推廣這個,所以log得到記錄,但它不會改變行動的簽名?

或者我需要2種方法,一種用於Action,另一種用於Action<T>

回答

3

你需要單獨的方法,但你可以ñ實現在其他方面的一個,以減少重複代碼:

鑑於現有Log(Action action, string log),您可以添加:

public static Action<T> Log<T>(this Action<T> action, string log) { 
    return t => Log(() => action(t), log); 
} 

或者周圍的其他方式:

public static Action<T> Log(this Action<T> action, string log) { 
    return t => { 
     Console.WriteLine(log); 
     action(t); 
    }); 
} 

public static Action Log(this Action action, string log) { 
    return() => Log<object>(t => action(), log); 
} 
2

您將需要兩種方法,因爲ActionAction<T>在此方案中彼此不兼容。

如果Action實際上是Action<void>來啓用此行爲,那將是有用的,但事實並非如此。

+0

呀,斯威夫特可以做那'因爲'Void'本身就是一個數據類型。我想知道C#是否也允許這樣做。 – vrwim

2

你可以使用類型Delegate併爲您提供操作的參數爲param object[]這樣的:

public static Action Log(this Delegate action, string log, params object[] args) 
{ 
    return() => 
    { 
     Console.WriteLine(log); 
     action.DynamicInvoke(args); 
    }; 
} 

你可以使用這個擴展這樣的:

Action<int> testAction = i => Console.WriteLine($"Test: {i}"); 
testAction.Log("Logging", 42).Invoke(); 

這導致了這個輸出:

Logging 
Test: 42 
+0

哦,我覺得OP要'Log '返回'Action '(意思是這個動作的參數不會傳遞給'Log') - 但OP沒有指定。你的解釋可能是對的。 – hvd

+0

是的,這不是我想到的,我想存儲生成的「Action」並稍後調用它。但這很好+1 – vrwim

+0

Upvote,因爲這是一個有趣的解決方案,但它涉及某種「動態模式」。由於我們使用的是C#,這是一種靜態類型的語言,因此@hvd解決方案更好。這也與您在.NET基礎框架和大多數可用庫中找到的內容一致。 –

相關問題