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

时间:2012-12-21 17:28:37

标签: c# 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
}

5 个答案:

答案 0 :(得分:10)

通过反思,你可以做更好的事情。

例如,声明一个接口

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());

答案 1 :(得分:1)

首先看一下适用于非抽象类的Get all inherited classes of an abstract class

然后你可以简单地在基类上调用每个方法。

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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(); // ??
}

答案 4 :(得分:0)

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

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