Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用反射或替代方法以编程方式创建函数调用?_C#_Reflection - Fatal编程技术网

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

C# 如何使用反射或替代方法以编程方式创建函数调用?,c#,reflection,C#,Reflection,我是个有点反省的新手。我希望有可能做我想做的事。我一直在通过ProjectEuler学习这门语言,我有一个叫做Problem的基类。每个体育问题都是一个单独的类,即问题16。要运行计算,我使用以下代码: using System; using Euler.Problems; using Euler.Library; namespace Euler { static class Program { [STAThread] static void M

我是个有点反省的新手。我希望有可能做我想做的事。我一直在通过ProjectEuler学习这门语言,我有一个叫做Problem的基类。每个体育问题都是一个单独的类,即问题16。要运行计算,我使用以下代码:

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
}
for(inti=1;i首先看一看哪种方法也适用于非抽象类

然后,您可以简单地调用基类上的方法

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

是的,这是可能的,您需要阅读MethodInfo。调用:

通过反射,您可以做更多更好的事情

例如,声明一个接口

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

作为一种可能的解决方案,我建议创建构造函数委托列表,而不使用反射。
您仍然需要填充列表50次,但只能填充一次。您将拥有typesafety,并且可以为每个派生类指定不同的构造函数。类似于以下内容:

 List<Func<Test>> tests = new List<Func<Test>>();
            tests.Add(() => new Test1());
            tests.Add(() => new Test2());
            foreach (var constructor in tests)
            {
                Test test = constructor();
            }
List tests=newlist();
添加(()=>newtest1());
添加(()=>newtest2());
foreach(测试中的var构造函数)
{
测试=构造函数();
}

这很酷。这可能是因为单元测试系统做了类似的事情。顺便说一句,这些问题有时需要相当多的计算时间。所以也许你不想每次都执行完整的problems@user287107我的三个最长执行时间分别为26秒、12秒和0.8秒-我的算法相当可靠。我只想创建一个文本文件报告,而不需要手动记录所有数据-因为我正在编写未来问题的代码,我一次只运行一个问题。@Oliver你知道这只需要一个问题吗?非常感谢。这是我的第一个问题,这里的社区不会让我失望。我是代码也简化了一点,但这给了我我所需要的!如果所有问题都源于问题,那么接口不会提供任何好处。简单地将它们作为问题来处理,就可以用较少的抽象来解决同样的问题。使用接口而不是抽象类有一个优势,即可以使用其他基类,例如。“组件”、“控件”、“表单”等等…我从这个答案开始,并与用户287107交叉引用,使我的代码运行良好。感谢您的指导!
 List<Func<Test>> tests = new List<Func<Test>>();
            tests.Add(() => new Test1());
            tests.Add(() => new Test2());
            foreach (var constructor in tests)
            {
                Test test = constructor();
            }