我只是添加了一些代码...因为。我同意,这段代码不太好看,但它相当简单直接。希望这能帮助那些偶然遇到这个问题的人。虽然已经测试过,但在生产环境中可能没有你想要的那样好:
使用参数args调用对象obj上的方法methodName:
public Tuple<bool, object> Evaluate(IScopeContext c, object obj, string methodName, object[] args)
{
// Get the type of the object
var t = obj.GetType();
var argListTypes = args.Select(a => a.GetType()).ToArray();
var funcs = (from m in t.GetMethods()
where m.Name == methodName
where m.ArgumentListMatches(argListTypes)
select m).ToArray();
if (funcs.Length != 1)
return new Tuple<bool, object>(false, null);
// And invoke the method and see what we can get back.
// Optional arguments means we have to fill things in.
var method = funcs[0];
object[] allArgs = args;
if (method.GetParameters().Length != args.Length)
{
var defaultArgs = method.GetParameters().Skip(args.Length)
.Select(a => a.HasDefaultValue ? a.DefaultValue : null);
allArgs = args.Concat(defaultArgs).ToArray();
}
var r = funcs[0].Invoke(obj, allArgs);
return new Tuple<bool, object>(true, r);
}
以下是函数 ArgumentListMatches,基本上取代了 GetMethod 中可能存在的逻辑:
public static bool ArgumentListMatches(this MethodInfo m, Type[] args)
{
var pInfo = m.GetParameters();
if (pInfo.Length < args.Length)
return false;
var commonArgs = args.Zip(pInfo, (margs, pinfo) => Tuple.Create(margs, pinfo.ParameterType));
if (commonArgs.Where(t => !t.Item1.IsAssignableFrom(t.Item2)).Any())
return false;
return pInfo.Skip(args.Length).All(p => p.IsOptional);
}
有很多LINQ,但这还没有经过性能测试!
此外,它无法处理通用函数或方法调用。这会使它变得更加丑陋(例如重复的GetMethod调用)。
MethodInfo
或ConstructorInfo
上调用 "Invoke"(不带参数)吗? - AlxandrMethodInfo
的情况下,有一个稍微不那么麻烦的重载:yourMethod.Invoke(target, Enumerable.Repeat(Type.Missing, 3).ToArray())
,其中target
在构造函数的情况下可能是null
。 - drzausEnumerable.Repeat()
提供的非常方便的代码片段,是的,在构造函数和静态方法的情况下,target
是null
。 - Manfred