Я просто добавлю код ... потому что. Я не согласен с этим кодом, но он довольно прямолинейный. Надеюсь, это поможет кому-то, кто спотыкается об этом. Испытано, хотя, вероятно, не так хорошо, как вы хотели бы в производственной среде:
Вызов метода имяМетода на объект OBJ с аргументами аргументах:
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)
{
// If there are less arguments, then it just doesn't matter.
var pInfo = m.GetParameters();
if (pInfo.Length < args.Length)
return false;
// Now, check compatibility of the first set of arguments.
var commonArgs = args.Zip(pInfo, (margs, pinfo) => Tuple.Create(margs, pinfo.ParameterType));
if (commonArgs.Where(t => !t.Item1.IsAssignableFrom(t.Item2)).Any())
return false;
// And make sure the last set of arguments are actually default!
return pInfo.Skip(args.Length).All(p => p.IsOptional);
}
Много LINQ, и это не было проверено на работоспособность!
Кроме того, это не будет обрабатывать вызовы общей функции или метода. Это делает это значительно более уродливым (как в повторных вызовах GetMethod).
Этот ответ на самом деле лучше, чем тот, который отмечен как правильный! –
Я могу подтвердить, что это работает. Я согласен, что это лучшее решение в большинстве случаев и, вероятно, должно быть отмечено как таковое. – N8allan
Можете ли вы просто вызвать «Invoke» (без параметров) в результате «MethodInfo» или «ConstructorInfo»? – Alxandr