Je vais juste ajouter un peu de code... parce que. Le code n'est pas plaisant, j'en conviens, mais il est assez simple. J'espère que cela aidera quelqu'un qui tombera dessus. Il est testé, mais probablement pas aussi bien que vous le voudriez dans un environnement de production :
Appel de la méthode methodName sur l'objet obj avec les arguments 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);
}
Et la fonction ArgumentListMatches est ci-dessous, qui prend essentiellement la place de la logique probablement trouvée dans 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);
}
Beaucoup de LINQ, et les performances n'ont pas été testées !
En outre, ce système ne gère pas les appels de fonctions ou de méthodes génériques. Cela rend le processus beaucoup plus laid (comme dans les appels GetMethod répétés).