如何使用反射设置方法的参数

时间:2012-03-19 11:45:16

标签: c# reflection

以下代码是我为系统创建的一个帮助程序,它允许管理员在数据库上创建自己的查询。它根据提供的方法和值返回lambda表达式。

我正在尝试找到一种将参数传递给方法调用的方法 - 在本例中,我使用StartsWith的{​​{1}}参数,并尝试将String设置为参数。

根据指定属性的类型,还需要其他参数。我希望了解提供字符串比较属性的方法将使我能够在以后添加其余的。

底层代码正常工作,我只需要它不区分大小写。

我使用this question作为指南,但此解决方案似乎并不适用。

以下是代码:

StringComparison.OrdinalIgnoreCase

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

在一般情况下,这应该有效:

public static Expression<Func<T, bool>>
Build(string propertyName, string method, params object[] args) 
{
    var propertyInfo = typeof(T).GetProperty(propertyName);
    var e = Expression.Parameter(typeof(T), "e");
    var m = Expression.MakeMemberAccess(e, propertyInfo);

    var mi = m.Type.GetMethod(method, args.Select(a => a.GetType()).ToArray());
    var c = args.Select(a => Expression.Constant(a, a.GetType())).ToArray();

    Expression call = Expression.Call(m, mi, c);

    Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(call, e);
    return lambda;
}

这个想法是你接受任意数量的常量参数,并在调用GetMethod时使用它们的类型来选择适当的重载。之后,从这些参数创建适当数量的常量表达式以传递给Expression.Call

所以使用上面的代码,你可以这样做:

var l1 = LambdaExpressionHelper<MailingListMember>.Build(
  "EmailAddress", "StartsWith", "RoRy@");
var l2 = LambdaExpressionHelper<MailingListMember>.Build(
  "EmailAddress", "StartsWith", "RoRy@", StringComparison.OrdinalIgnoreCase);

如果您还需要从字符串StringComparison.OrdinalIgnoreCase获取值"StringComparison.OrdinalIgnoreCase",我会将其分解为一个单独的方法,以便Build的接口可以保持通用。究竟如何做到这一点在Getting Enum value via reflection中有所涉及(我猜也有很多类似的问题)。

注意:我现在无法方便地访问编译器,所以请原谅任何错误。

答案 1 :(得分:0)

我不确定我是否完全理解你的问题,但希望这会对你有所帮助。

如果您使用的是.NET 4.0,则可以使用新的关键字“dynamic”来更容易地反映代码:

dynamic myDynamicObj = "Hello World!"; // or Activator.CreateInstance...
var doesIndeed = myDynamicObj.StartsWith("Hello", StringComparison.OrdinalIgnoreCase);

这会在运行时进行评估,因此请确保拼写/案例等正确无误。

编辑: 假设你总是想用一个String-arg返回bool调用方法,可能的解决方案是创建一个委托类型 -

delegate bool CompareString(String str);

并且将Build的第二个参数作为该类型:

Build(String .., CompareString cs, String ...)

但是如果你需要添加额外的参数,这不起作用,如StringComparison类型的第二个arg。 if / switch可能是答案,即if(CompareString是StartsWith)......

抱歉,不是在Windows电脑上,所以我无法进一步测试。