8

我对反射有点新手。我希望有可能做我想做的事。我一直在通过 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 个问题,我想创建一个循环来运行它们。我的基类 Problem 有一个方法可以将问题编号、答案和在每个类的默认构造函数中调用的执行时间附加到文本文件中。我可以手动更改所有 50 个函数的调用,但随着我继续完成问题,这最终会成为很多工作。

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

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

5 回答 5

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());
于 2012-12-21T17:36:27.983 回答
1

首先看一下获取抽象类的所有继承类,它也适用于非抽象类。

然后您可以简单地为每个调用基类上的方法。

foreach (problem p in problems)
{
  p.MyMethod()
}
于 2012-12-21T17:34:22.683 回答
0

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

于 2012-12-21T17:34:48.407 回答
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(); // ??
}
于 2012-12-21T17:35:10.013 回答
0

As one of the possible solutions, I would like to propose to create list of constructor delegates without the use of reflection.
You will still have to populate the list 50 times, but only once. You will have typesafety though and can specify different constructors for each of the derived classes. Something like this:

 List<Func<Test>> tests = new List<Func<Test>>();
            tests.Add(() => new Test1());
            tests.Add(() => new Test2());
            foreach (var constructor in tests)
            {
                Test test = constructor();
            }
于 2012-12-21T18:29:23.880 回答