如何使用动态返回传递“Func”列表的“参数”

本文关键字:列表 参数 Func 动态 何使用 返回 | 更新日期: 2023-09-27 18:37:19

我需要调用一个接收Func<T> list的方法,问题是列表的所有项目Func的返回并不相同。

例如:

//Having the following method:
public void DoSomething(params Expression<Func<T>> list)
{
   //get the property info to get the name and value
   // PropertyInfo p = (propertyExpression.Body as MemberExpression).Member as PropertyInfo;
   //EDIT: Using the answer to change the T to object I needed to get the property info using this: 
   (((UnaryExpression)propertyExpression.Body).Operand as MemberExpression).Member as PropertyInfo;
}
//and the following object
public class Foo
{
    public long Id { get;set; } //LOOK: ITS A LONG PROPERTY
    public string Name { get; set; } // ITS A STRING PROPERTY
}
//I would like to pass these two expressions of DIFFERENT returning types.
Foo f = new Foo();
DoSomething(() => f.Id, () => f.Name); //TWO RETURN TYPES DIFFERENTS.

编译器说这是不可能的,因为方法参数是一个Generic Type T,所以所有传递的 Funcs 都需要是相同的返回类型。

如何使用动态返回传递“Func<T>”列表的“参数”

使用 params Expression<Func<object>>[] list 作为参数,而不是 T(请注意,它必须是与 params 一起使用的数组)

当然,您需要转换结果才能使用它(除非您的流程可以使用object......比如说在DoSomething里面做一个ToString(),但是当T根据参数的不同而不同时,你还期望如何使用T

更新:我在这个小提琴中做了一个例子,但你能用它做的事情几乎是有限的,所以正如@juharr评论中所述,如果你解释你想做什么会更好,这样我们就可以建议更实用的替代方案

另外,如果你不需要表达式

(只是回调),则不需要传递表达式,只需传递Func(修改后的小提琴)

好吧

,它并不漂亮,但我认为这是它与泛型一起使用的唯一方法。这可能不是一个实用的解决方案:

public void DoSomething<T>(Expression<Func<T>> p)
{
}
public void DoSomething<T1,T2>(Expression<Func<T1>> p1,Expression<Func<T2>> p2)
{
}
public void DoSomething<T1,T2,T3>(Expression<Func<T1>> p1,Expression<Func<T2>> p2,Expression<Func<T3>> p3)
{
}
//etc...

Microsoft用它的 Func deliments 做萨米的事情

public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, inT7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, out TResult>(
    T1 arg1,
    T2 arg2,
    T3 arg3,
    T4 arg4,
    T5 arg5,
    T6 arg6,
    T7 arg7,
    T8 arg8,
    T9 arg9,
    T10 arg10,
    T11 arg11,
    T12 arg12,
    T13 arg13,
    T14 arg14
) 

一种可能性是使用流畅的接口而不是列表

public object Command
{
    public void DoSomething()
    {
       //do something, act on values stored in member var;
    }
    public Command AddProp<T>(Expression<Func<T>> propAndValue)
    {
       // Get property and value from expression
       // store in member var
       return this;
    }
}

public class Foo
{
    public long Id { get;set; } //LOOK: ITS A LONG PROPERTY
    public string Name { get; set; } // ITS A STRING PROPERTY
}
// Example usage
Foo f = new Foo();
Command cmd = new Command();
cmd.AddProp(() => f.Id).AddProp(() => f.Name).DoSomething();