gpt4 book ai didi

c# - 如何使用反射调用带参数的非泛型静态扩展方法

转载 作者:行者123 更新时间:2023-11-30 22:30:13 25 4
gpt4 key购买 nike

我正在使用下面的代码来执行方法。它适用于 string 的标准方法,例如 StartsWith,但是我正在尝试使用几种字符串扩展方法,包括对 Contains 的覆盖允许不区分大小写:

var method = "Contains";
var args = new object[] { "@", StringComparison.OrdinalIgnoreCase };

// This works when called
var mi = m.Type.GetMethod(method, args.Select(a => a.GetType()).ToArray());
if (mi == null) {
// This does find the method, but causes an error on Expression.Call below
mi = typeof(Extensions).GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(meth => meth.Name == method);
}

var c = args.Select(a => Expression.Constant(a, a.GetType()));

return Expression.Lambda<Func<T, bool>>(Expression.Call(m, mi, c), e);

我收到的错误是:

Static method requires null instance, non-static method requires non-null instance.

我该如何解决这个问题?

作为引用,这里是 Contains 扩展:

public static bool Contains(this string source, string toCheck, StringComparison comp) {
return source.IndexOf(toCheck, comp) >= 0;
}

谢谢


编辑

根据 Balazs 的回答进行了更新,尽管我现在收到以下错误:

Expression of type 'System.Linq.Expressions.PropertyExpression' cannot be used for parameter of type 'System.String' of method 'Boolean Contains(System.String, System.String, System.StringComparison)'

完整的方法供引用:

public static Expression<Func<T, bool>> Build(string member, IEnumerable<object> memberArgs, string method, params object[] args) {
var e = Expression.Parameter(_type, "e");
var memberInfo =
(MemberInfo) _type.GetField(member) ??
(MemberInfo) _type.GetProperty(member) ??
(MemberInfo) _type.GetMethod(member, (memberArgs ?? Enumerable.Empty<object>()).Select(p => p.GetType()).ToArray());
Expression m;

if (memberInfo.MemberType == MemberTypes.Method) {
var a = memberArgs.Select(p => Expression.Constant(p));
m = Expression.Call(e, (MethodInfo) memberInfo, a);
}
else {
m = Expression.MakeMemberAccess(e, memberInfo);
}

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

if (mi != null) {
call = Expression.Call(m, mi, c);
}
else {
mi = typeof(Extensions).GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(meth => meth.Name == method);
var newArgsList = c.ToList<object>();
newArgsList.Insert(0, m);
c = newArgsList.Select(a => Expression.Constant(a, a.GetType()));
call = Expression.Call(null, mi, c);
}

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

最佳答案

您必须传递一个null ConsantExpression 作为Expression.Call 的实例参数,并添加m 作为 中的第一个参数>c.

关于c# - 如何使用反射调用带参数的非泛型静态扩展方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9786153/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com