重放函数和参数列表

本文关键字:参数 列表 函数 | 更新日期: 2023-09-27 18:18:39

我有一系列函数,我希望具有以下功能。

  • 当函数被调用时,将自己添加到函数列表中,记住参数和值
  • 允许在以后的日期调用函数列表

不同的函数有各种不同的参数,我正在努力想出一种优雅的方法来做到这一点。

重放函数和参数列表

我认为这将满足您的需求,但是功能并没有"添加自己"。

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库,比如postsharp或linfu动态代理,并添加一个拦截器,它将函数和参数添加到数组中。在我看来,这样做可能比值得做的工作要多,因为上面的代码要简单得多,而且仍然实现了预期的功能。

几乎没有一个优雅的解决方案。由于您说这些方法都有不同的签名,因此无法将它们作为委托存储在单个数组中。解决了这个问题,接下来您可以尝试使用反射,将每个参数值存储在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)

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

我不确定我理解你的问题,但我认为你可以使用指针数组的函数(在c#中它被称为委托)。所以当函数被调用时,把函数指针放在一个列表中。通过这种方式,你可以从列表中调用函数。这里有一些想法。请注意,当您添加新的委托指针到列表(functionPointers),在第二个列表myParameters中,您添加类型为Parameters的新对象,该对象在称为parameters的公共属性中保存函数参数。这意味着列表functionPointers中的委托i具有列表myParameters中的i -第一个对象。这就是你如何知道哪个参数,对应哪个函数。也许有更好的解决方案,但这只是一个选择。

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

}

你可以考虑使用一个动作或函数列表

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的非常相似