Ich werde nur etwas Code hinzufügen ... weil. Der Code ist nicht angenehm, stimme ich zu, aber es ist ziemlich geradlinig. Hoffentlich wird dies jemandem helfen, der darüber stolpert. Es wird getestet, wenn auch wahrscheinlich nicht so gut wie Sie in einer Produktionsumgebung wünschen würden:
Aufruf der Methode-Methode für Objekt obj mit Argumenten args:
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);
}
und die Funktion ArgumentListMatches unten ist, die im Grunde die Takes Stelle der Logik wahrscheinlich in GetMethod gefunden:
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);
}
Viele LINQ, und dies nicht die Leistung getestet!
Dies wird auch keine generischen Funktions- oder Methodenaufrufe verarbeiten. Das macht dies wesentlich hässlicher (wie bei wiederholten GetMethod-Anrufen).
Diese Antwort ist eigentlich besser als die, die als richtig markiert ist! –
Ich kann bestätigen, dass das funktioniert. Ich stimme zu, dass dies in den meisten Fällen eine bessere Lösung ist und wahrscheinlich als solche gekennzeichnet werden sollte. – N8allan
Kann man "Invoke" (ohne Parameter) einfach auf der resultierenden 'MethodInfo' oder' ConstructorInfo' aufrufen? – Alxandr