我正在尝试创建一个带有参数的func的扩展方法。我想支持可变数量的参数(无,1,2,... 10)
我有类似的东西适用于三个参数。 如何简化它以支持可变数量的参数,而不必为每个排列复制和粘贴?它甚至可能吗?
(注意:我的示例非常简单。我的实际实现有更多逻辑,例如支持具有计数的'重试'逻辑,Thread.Sleep,跟踪日志记录,异常处理等。)
谢谢!
public static class UtilExtensions
{
public static TResult Execute<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> function, T1 argument1, T2 argument2, T3 argument3))
{
// do other stuff ... like logging
try
{
// call our 'action'
TResult result = function(argument1, argument2, argument3);
return result;
}
catch (Exception ex)
{
// do other stuff ... like logging, handle Retry logic, etc.
}
}
}
,它被调用如下:
public string DoSomething(int arg1, string arg2, MyObject arg3)
{
if (arg1 == 1)
throw new Exception("I threw an exception");
return "I ran successfully";
}
public string DoSomethingElse()
{
return "blah blah blah";
}
public string DoSomethingMore(DateTime dt)
{
return "hi mom";
}
[TestMethod]
public void Should_call_UtilsExtensions_Execute_method_successfully()
{
int p1 = 0;
string p2 = "Hello";
MyObject p3 = new MyObject();
string results = UtilExtensions.Execute<int, string, MyObject, string>(
DoSomething, p1, p2, p3);
// ??? So how would I use my UtilExtensions api to call
// DoSomethingElse (no arguments)
// DoSomethingMore (one argument)
// I'm okay to create overloads of my Execute method
// but I don't want to copy-and-paste the same code/logic in each method
results.Should().Be("I ran successfully");
}
答案 0 :(得分:2)
我认为你不能这样做,据我所知,这正是Func和Action类型对.Net中不同参数号有许多不同声明的原因。请参阅https://msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx
的左侧你问的是类似的东西,除非在这种情况下OP询问接口Can I have a variable number of generic parameters?
问题基本上与仿制药的基本限制相同。
你可能能够用反射做一些事情,但我认为你最好选择合理数量的参数来支持和编写重载。
Params不起作用,因为对于params,数组中的所有类型都是相同的类型。 T1,T2等是不同类型供您使用。你必须将params声明为Object [],这完全违背了泛型。虽然你可能愿意放弃类型检查,如果你真的有一个未知数量的参数可能是不切实际的高。
答案 1 :(得分:1)
你不能这样做。另一种方法是创建一个接受一个参数的扩展方法,但该参数可以由匿名函数组成。因此,您的调用代码将完全控制如何使用它。不是最干净,但至少比代码生成器路径更清洁:
public static class UtilExtensions
{
public static TResult Execute<TResult>(this Func<TResult> function)
{
// do logging
try
{
TResult result = function();
return result;
}
catch (Exception ex)
{
// do other stuff ... like logging, handle Retry logic, etc.
}
// or throw - this right here could prove unpredictable and is verrrry dirty
return default(TResult);
}
}
用法:
var param1 = 1;
var param2 = "string";
Func<bool> function = () =>
{
// do stuff with param1 and param2
return true;
}
var results = function.Execute();