动态设置Func<>类型

时间:2012-04-16 14:42:54

标签: c# types func

有没有办法动态设置Func<>类型参数,所以我不必使用无穷无尽的if语句?

类似的东西:

Type t = Type.GetType("System.Decimal");
Func<t> foo = new Func<t>(some_function);

而不是:

Func<Decimal> foo = new Func<Decimal>(some_function);

更新:

以下是我的代码中的代码段:

Type t = typeof(StavkaDokumenta).GetProperty(pd.Polje).PropertyType;
ParameterExpression pe = Expression.Parameter(typeof(StavkaDokumenta), "stavka");
Expression expr = Expressions.ResolveCompleteExpression(pe, pd.Expression);
Expression final = Expression.Convert(expr, t);
if (t == typeof(decimal))
{
    var lambda = Expression.Lambda<Func<StavkaDokumenta, decimal>>(final, pe);
    o = lambda.Compile().Invoke(stavka);
}
if (t == typeof(decimal?))
{
    var lambda = Expression.Lambda<Func<StavkaDokumenta, decimal?>>(final, pe);
    o = lambda.Compile().Invoke(stavka);
}
else if (t == typeof(int))
{
    var lambda = Expression.Lambda<Func<StavkaDokumenta, int>>(final, pe);
    o = lambda.Compile().Invoke(stavka);
}
else if (t == typeof(int?))
{
    var lambda = Expression.Lambda<Func<StavkaDokumenta, int?>>(final, pe);
    o = lambda.Compile().Invoke(stavka);
}
else if (t == typeof(string))
{
    var lambda = Expression.Lambda<Func<string>>(final, null);
    o = lambda.Compile().Invoke();
}

pd.Polje是字符串 - “StavkaDokumenta”类中属性的名称。 pd.Expression是字符串表达式,必须根据Polje的类型进行评估。 stavka是StavkaDokumenta的一个实例。

1 个答案:

答案 0 :(得分:9)

既然你展示了你真正想要的东西,答案就更简单了: 由于您显然只对该表达式的返回值感兴趣,因此您可以将代码更改为:

Type t = typeof(StavkaDokumenta).GetProperty(pd.Polje).PropertyType;
ParameterExpression pe = Expression.Parameter(typeof(StavkaDokumenta), "stavka");
Expression expr = Expressions.ResolveCompleteExpression(pe, pd.Expression);
Expression final = Expression.Convert(expr, t);

if (t == typeof(string))
{
    var lambda = Expression.Lambda<Func<string>>(final, null);
    o = lambda.Compile().Invoke();
}
else
{
    var lambda = Expression.Lambda(final, pe);
    o = lambda.Compile().DynamicInvoke(stavka);
}

旧答案:

您可以使用泛型和隐式转换Func<T>来实现此目的:

Func<T> GetFunc<T>(Func<T> func)
{
    return func;
}

使用类似方法组调用它:

var foo = GetFunc(SomeMethod);

这假设SomeMethod看起来像这样:

decimal SomeMethod()
{
    // ...
}

foo的类型为Func<decimal>。如果SomeMethod的返回类型为string,则foo的类型将为Func<string>


此代码中发生的情况如下:

传递给GetFunc的参数是所谓的“方法组”,而不是Func<T>类型的变量。但是,存在从方法组到Func<T>

变量的隐式转换
Func<decimal> func = SomeMethod; // an implicit conversion happens here

隐式转换正是这里发生的事情:在调用GetFunc之前,方法组SomeMethod被转换为Func<T>类型的变量。编译器还根据方法T的返回类型推断出SomeMethod()使用的具体类型。
我们的目标是根据我们的方法组创建Func<T>的实例。因为在调用方法之前已经在参数转换中发生了这种情况,我们只需从方法中返回该创建的实例。