如何使用reflection或替代方法以编程方式创建函数调用?

我有点像reflection的新手。 我希望能做到我喜欢的事情。 我一直在通过ProjectEuler学习语言,我有一个名为Problem的基类。 每个PE问题都是一个单独的类,即Problem16。 要运行我的计算,我使用以下代码:

using System; using Euler.Problems; using Euler.Library; namespace Euler { static class Program { [STAThread] static void Main() { Problem prob = new Problem27(); } } } 

我现在已经完成了50个问题,我想创建一个循环来运行它们。 我的基类问题有一个方法,它在文本文件中附加问题编号,答案和在每个类的默认构造函数中调用的执行时间。 我可以手动更改所有50的函数调用,但是当我继续完成问题时,这将最终成为很多工作。

我宁愿以编程方式来做。 我希望这个伪代码成为现实:

 for (int i = 1; i <= 50; i++) { string statement = "Problem prob = new Problem" + i + "();"; // Execute statement } 

有了反思,你可以做更好的事情。

例如,声明一个接口

 interface IEulerProblem { void SolveProblem(); } 

编写从IEulerProblem派生的类。

那么你可以运行(技术上)一行很好的代码:

 Assembly.GetEntryAssembly() .GetTypes() .Where(t => typeof(IEulerProblem).IsAssignableFrom(t)) .Where(t => !t.IsInterface && !t.IsAbstract) .Select(t => Activator.CreateInstance(t) as IEulerProblem) .OrderBy(t => t.GetType().Name).ToList() .ForEach(p => p.SolveProblem()); 

首先来看看Get的所有inheritance类,它们也适用于非抽象类。

然后,您只需在基类上调用每个方法。

 foreach (problem p in problems) { p.MyMethod() } 

是的,这是可能的,您需要阅读MethodInfo.Invoke: http : //msdn.microsoft.com/en-us/library/system.reflection.methodinfo.invoke.aspx

 var problems = Assembly.GetExecutingAssembly().GetTypes() .Where(t => !t.IsAbstract && typeof(Problem).IsAssignableFrom(t)); foreach(var p in problems) { var euler = Activator.CreateInstance(p) as Problem; euler.Solve(); // ?? } 

作为可能的解决方案之一,我想建议在不使用reflection的情况下创建构造函数委托列表。
您仍然需要填充列表50次,但只需填充一次。 您将拥有类型安全性,并且可以为每个派生类指定不同的构造函数。 像这样的东西:

  List> tests = new List>(); tests.Add(() => new Test1()); tests.Add(() => new Test2()); foreach (var constructor in tests) { Test test = constructor(); }