2011-12-21 50 views
8

我有一系列功能,我希望具有以下功能。重播功能和參數列表

  • 當函數被調用時,其自身添加到的記住參數的功能列表和值
  • 允許的功能列表,在以後的日子

不同的功能有一個被稱爲各種不同的參數,我正在努力想辦法做到這一點。任何幫助,將不勝感激。

+0

所有這些函數都具有相同的簽名還是會有所不同?你會回憶這些功能相同的論點,還是會改變? – 2011-12-21 01:50:14

+0

@JeffMercado它們會與可變數量的參數和返回類型不同。 – 2011-12-21 01:51:43

+2

也許看看這個問題。 http://stackoverflow.com/questions/377217/c-sharp-delegate-for-two-methods-with-different-parameters它可能不是你想要做的同樣的事情,但它談論運行委託與不同的參數。 – 2011-12-21 02:04:57

回答

9

調用我認爲這將滿足您的需求,但功能沒有「並稱自己」。使函數「添加自己」

public class Recorder 
{ 
    private IList<Action> _recording; 
    public Recorder() 
    { 
     _recording = new List<Action>(); 
    } 
    public void CallAndRecord(Action action) 
    { 
     _recording.Add(action); 
     action(); 
    } 
    public void Playback() 
    { 
     foreach(var action in _recording) 
     { 
      action(); 
     } 
    } 
} 

//usage 
var recorder = new Recorder(); 
//calls the functions the first time, and records the order, function, and args 
recorder.CallAndRecord(()=>Foo(1,2,4)); 
recorder.CallAndRecord(()=>Bar(6)); 
recorder.CallAndRecord(()=>Foo2("hello")); 
recorder.CallAndRecord(()=>Bar2(0,11,true)); 
//plays everything back 
recorder.Playback(); 

的一種方法是使用一個AOP LIB如postsharp或李林甫動態代理,並添加一個攔截器這增加了功能和args到陣列。要做到這一點可能會比值得的IMO更多的工作,因爲上述更簡單,並仍然實現所需的功能。

+0

幹得好,這是最棒的! – MrD 2011-12-21 02:44:36

+0

確實,出色的解決方案。 – 2011-12-21 03:16:50

+0

非常好的答案。 +1 – 2011-12-22 03:18:43

1

我不知道我理解你的問題,但我認爲你可以使用指向數組的指針(在C#中它被稱爲委託)。所以當函數被調用時,把函數指針放在一個列表中。這樣你可以從列表中調用函數。這是一些想法。注意,當您將新代表指針添加到列表(functionPointers)時,請在第二個列表myParameters中添加類型爲Parameters的新對象,該對象在公共屬性parameters中保存函數參數。這意味着代表i在參數列表functionPointers中的參數具有i列表中的第012個對象myParameters。這是你如何知道哪些參數,是哪個功能。可能有一些更好的解決方案,但這是替代方案。

delegate void NewDelegate(); 
class Parameter{ 
    public ArrayList parameters; 

} 
ArrayList functionPointers=new ArrayList(); 
ArrayList<Parameter> myParameters=new ArrayList<Parameter>(); 
NewDelegate myDelegate; 

void someFunction(int a, int b){ 
    myDelegate+=someFunction;//you add this function to delegate because this function is called 
    functionPointers.add(myDelegate);//Add delegete to list 
    Parameter p=new Parameter();//Create new Parameter object 
    p.parameters.add(a);//Add function parameters 
    p.parameters.add(b); 
    myParameters.add(p);//add object p to myParameters list 

}

+0

這段代碼甚至沒有編譯。您無法將任何方法存儲到無參數委託。您必須遵循方法簽名規則。 – 2011-12-21 02:41:00

5

這幾乎沒有一個優雅的解決方案。既然你說過這些方法都有不同的簽名,那麼就沒有辦法將它們作爲代理存儲在單個數組中。除此之外,接下來您可以嘗試使用反射,將每個參數值存儲在object []中,將方法存儲爲MethodInfo,然後調用它。

編輯:這是我能想出:

private Dictionary<MethodBase, object[]> methodCollection = new Dictionary<MethodBase, object[]>(); 

    public void AddMethod(MethodBase method, params object[] arguments) 
    { 
     methodCollection.Add(method, arguments); 
    } 

    private void MyMethod(int p1, string p2, bool p3) 
    { 
     AddMethod(System.Reflection.MethodInfo.GetCurrentMethod(), new object[] { p1, p2, p3 }); 
    } 

    private void MyOtherMethod() 
    { 
     AddMethod(System.Reflection.MethodInfo.GetCurrentMethod(), new object[] { }); 
    } 

然後只需用method.Invoke(method.ReflectedType, args)

+0

+1這更多的是我想說的......但是用DynamicInvoke來做。我以前從來沒有真正使用它,所以我可以離開基地。 – 2011-12-21 02:29:13

+0

要使用DynamicInvoke,您需要Delegate實例,爲此您需要Type和MethodInfo,以便您可以使用'Delegate.CreateDelegate()'創建委託,這與基本相同,只需幾個步驟。你仍然需要反思。 – 2011-12-21 02:37:36

1

如果要存儲參數以及和有你可以使用FUNC鍵,存儲和多用同樣的方式

你可以考慮使用一個動作列表或功能

using System; 
using System.Collections.Generic; 

namespace ReplayConsole 
{ 
class Program 
{ 
    private static IList<Action> _actions; 

    static void Main(string[] args) 
    { 
     _actions = new List<Action> 
        { 
         () => { 
          //do thing 
         }, 
         () => { 
          //do thing 
         }, 
         () => { 
          //do thing 
         }, 
         () => { 
          //do thing 
         }, 
        }; 

     foreach (var action in _actions) 
     { 
      action(); 
     } 
    } 
} 

您還可以看看Tasks

編輯:

看着那突然出現了,而我在寫我的這個搜索解決方案的答案n與Brook's非常相似