Tôi sẽ chỉ thêm một số mã ... vì. Mã không vui, tôi đồng ý, nhưng nó khá thẳng về phía trước. Hy vọng rằng điều này sẽ giúp một người tình cờ hiểu được điều này. Nó được thử nghiệm, mặc dù có lẽ không cũng như bạn muốn trong một môi trường sản xuất:
gọi method methodName trên đối tượng obj với đối số 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);
}
Và ArgumentListMatches chức năng là dưới đây, về cơ bản có các vị trí của logic có thể được tìm thấy trong 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);
}
Rất nhiều LINQ, và điều này chưa được kiểm tra hiệu suất!
Ngoài ra, điều này sẽ không xử lý các chức năng hoặc cuộc gọi phương thức chung. Điều đó làm cho điều này xấu hơn đáng kể (như trong các cuộc gọi GetMethod lặp đi lặp lại).
Câu trả lời này thực sự tốt hơn câu trả lời được đánh dấu là đúng! –
Tôi có thể chứng thực rằng tác phẩm này hoạt động. Tôi đồng ý rằng đây là giải pháp tốt hơn trong hầu hết các trường hợp và có lẽ nên được đánh dấu như vậy. – N8allan
Bạn có thể gọi đơn giản là "Gọi" (không có tham số) trên 'MethodInfo' hoặc' ConstructorInfo' kết quả không? – Alxandr