重播功能和参数列表

时间:2011-12-21 01:42:22

标签: c# function reflection delegates

我有一系列功能,我想拥有以下功能。

  • 调用该函数时,将其自身添加到记住参数和值的函数列表中
  • 允许稍后调用函数列表

不同的功能有各种不同的参数,我很难想到一个优雅的方法来做到这一点。任何帮助将不胜感激。

5 个答案:

答案 0 :(得分: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();

使函数“自我添加”的一种方法是使用诸如postharp或linfu动态代理之类的AOP库,并添加一个拦截器,它将函数和args添加到数组中。要做到这一点可能会比IMO更值得工作,因为上面的内容要简单得多,并且仍能实现所需的功能。

答案 1 :(得分: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)

进行调用

答案 2 :(得分:3)

也许你可以使用Delegate.DynamicInvoke(Object[] obj)函数。您可以将每个方法添加到对象数组中,然后遍历调用每个方法上的DynamicInvoke的数组。

答案 3 :(得分:1)

我不确定我理解你的问题,但我认为你可以使用函数指针数组(在C#中它被称为委托)。因此,当调用函数时,将函数指针放在列表中。通过这种方式,您可以从列表中调用函数。这是一些想法。请注意,当您将新的委托指针添加到列表(functionPointers)时,在第二个列表myParameters中添加新的Parameters对象,该对象在名为parameters的公共属性中保存函数参数。这意味着参数列表i中的委托functionPointers具有i - 列表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

}

答案 4 :(得分:1)

您可以考虑使用操作或功能列表

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();
        }
    }
}

如果你想存储参数,你可以使用Func并以相同的方式存储和使用它

您还可以查看Tasks

编辑:

看着我写作时出现的答案,这个解决方案与Brook的非常相似