调用签名未知的方法

时间:2019-01-30 11:47:06

标签: c#

我正在使用C#4.6.2,但如果可以的话,可以升级到4.7.2。

在我们代码的许多地方,我们都有一个带有等待语句的循环,以在调用函数时检查特定的值,如果在最大重试次数之前不是我们想要的值,请等待并重试。

我想对此进行抽象,但是我能想到的唯一实现要求您传入一个带有可变数量变量类型的方法,这种方法经过Google的大量搜索似乎在大约5年后不可能实现。前。从那时起,C#有了很多改进,所以

  1. 仍然不可能吗?
  2. 如果现在有可能怎么办?
  3. 如果不可能的话,您能想到我实现目标的任何其他方式吗?

我正在寻找的东西是:

public bool GenericLoopWait(int maxWaitSeconds, int waitMsPerIteration,??? DoSomething,object expectedResult,...)
    int maxRetries = maxWaitSeconds*1000/waitMsPerIteration;
    SomeType result=null;
    for(int i=0; i<maxRetries; i++){
        result = DoSomething(...);
        if(result==expectedResult) break;
        Thread.Sleep(waitMsPerIteration);
    }
    return result==expectedResult
}

然后这两个都可以工作:

GenericLoopWait(5,500,Browser.Webdriver.FindElements(selector).Any(),true);
GenericLoopWait(5,500,Api.GetSpecificObject(api,objectName),"expectedOutcome");

2 个答案:

答案 0 :(得分:7)

您可以使用泛型和Func并在调用方法时包装实际的调用参数。

public bool GenericLoopWait<T>(int maxWaitSeconds, int waitMsPerIteration, Func<T> DoSomething, T expectedResult = default(T))
{
    int maxRetries = maxWaitSeconds * 1000 / waitMsPerIteration;
    T result = default(T);
    for (int i = 0; i < maxRetries; i++)
    {
        result = DoSomething();
        if (expectedResult.Equals(result)) break;
        Thread.Sleep(waitMsPerIteration);
    }

    return expectedResult.Equals(result);
}

呼叫代码:

GenericLoopWait(5, 500, () => Browser.Webdriver.FindElements(selector).Any(), true);
GenericLoopWait(5, 500, () => Api.GetSpecificObject(api,objectName), "expectedOutcome")

Working dotnetfiddle

答案 1 :(得分:0)

通常的模式是创建一个接受ActionFunc作为参数的“ Wrapper”方法。包装器可以执行自己的逻辑,并在正确的时间Invoke设置参数。

作为一个简单的通用示例:

public void MethodWrapper(Action action)
{
    Console.WriteLine("begin");
    action.Invoke();
    Console.WriteLine("end");
}

然后您可以执行以下操作:

void Main()
{
    var a = 1;
    var b = 2;

    MethodWrapper(() => DoSomething(a));
    MethodWrapper(() => DoSomethingElse(a,b));
}

public void DoSomething(int a)
{
    Debug.WriteLine($"a={a}");
}

public void DoSomethingElse(int a, int b)
{
    Debug.WriteLine($"a={a}, b={b}");
}

要生成此输出:

  

开始
  a = 1
  结束
  开始
  a = 1,b = 2
  结束

对于您的特定情况,包装器可以使用其他参数来指定诸如重试次数,两次呼叫之间的时间或接受条件之类的东西。