Voy a agregar un código ... porque. El código no es agradable, estoy de acuerdo, pero es bastante directo. Espero que esto ayude a alguien que tropiece con esto. La prueba se hace, aunque probablemente no tan bien como le gustaría que en un entorno de producción:
Llamando al método methodName en el objeto obj con argumentos 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);
}
Y los ArgumentListMatches función está por debajo, que básicamente toma la lugar de la lógica, probablemente, que se encuentra en 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);
}
Un montón de LINQ, y esto no ha sido probado rendimiento!
Además, esto no manejará funciones genéricas o llamadas a métodos. Eso hace que esto sea significativamente más feo (como en las llamadas GetMethod repetidas).
¡Esta respuesta es mejor que la marcada como la correcta! –
Puedo dar fe de que esto funciona. Estoy de acuerdo en que esta es una solución mejor en la mayoría de los casos y probablemente deba marcarse como tal. – N8allan
¿Se puede simplemente llamar a "Invocar" (sin parámetros) en el 'MethodInfo' o' ConstructorInfo' resultante? – Alxandr