5

我的老板让我研究计算引擎。实际上,用户将拥有一个可以执行计算的数据表。他们还将能够根据我们强制执行的某些限制构建自己的计算(然后将构建的计算存储在数据库中)

是否可以在 C# 中调用特定方法,具体取决于数据库中存储的内容?因此,如果数据库说,计算应该执行标准偏差。当我们从数据库中获取该信息时,是否可以调用我们将在 C# 中使用的标准偏差方法?

我希望这很清楚。

4

6 回答 6

3

考虑到将对您的数据执行的少量/已知操作,我会选择根据从数据库中检索到的数据手动编码这些操作。对于可扩展性/可维护性,最好为此创建适当的设计,而不是使用简单的 switch 语句。我猜策略模式将适合您的需求。

正如其他人所说,您可以使用反射来调用数据库中指定的方法。这种方法的问题是数据库中的数据与方法签名密切相关。与第一种方法相比,这种方法的可维护性较差,但确实可以通过最少的代码调整实现出色的可扩展性。另一个缺点是使用MethodInfo.Invoke()速度相当慢。

如果您选择反射,但发现该Invoke()方法太慢,我可以推荐Jon Skeet 的这篇文章,它解释了如何将 MethodInfo 转换为委托实例。这大大提高了速度。我最近为此使用表达式树编写了一个通用实现。

总而言之,选项 1 似乎仍然是最适合您的目的。

于 2011-03-04T13:34:11.570 回答
2

是的,这是可能的;它被称为反射,它是标准的 C# 功能。网上有很多教程。这是一些非常简单的示例代码:

using System;
using System.Reflection;

class CallMethodByName
{
   string name;

   CallMethodByName (string name)
   {
      this.name = name;
   }

   public void DisplayName()      // method to call by name
   {
      Console.WriteLine (name);   // prove we called it
   }

   static void Main()
   {
      // Instantiate this class
      CallMethodByName cmbn = new CallMethodByName ("CSO");

      // Get the desired method by name: DisplayName
      MethodInfo methodInfo = 
         typeof (CallMethodByName).GetMethod ("DisplayName");

      // Use the instance to call the method without arguments
      methodInfo.Invoke (cmbn, null);
   }
}

http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string

于 2011-03-04T13:08:26.427 回答
0

您可以使用 C# 中的 switch 语句来执行您想要的操作,具体取决于来自数据库的记录字段(或标量)的值。如果您支持的操作数量很少/有限,这是可以的,否则您当然可以使用反射和 MethodInfo 类通过某个类上的“字符串名称”调用成员方法。

于 2011-03-04T13:05:55.370 回答
0

您可以将操作存储在数据库中并用于Microsoft.CSharp.CSharpCodeProvider即时编译代码。

在此处查看示例:在运行时执行代码

于 2011-03-04T13:07:29.740 回答
0

我建议你实施策略模式(http://www.dofactory.com/Patterns/PatternStrategy.aspx

您可以为所需的不同计算加载不同的策略(算法)。

还有一个不错的帖子http://blogs.microsoft.co.il/blogs/gilf/archive/2009/11/22/applying-strategy-pattern-instead-of-using-switch-statements.aspx

于 2011-03-04T13:10:19.190 回答
0

是的,您可以使用反射来做到这一点。您可以编写一个包含用户可以执行的所有操作的类,然后动态调用其方法。

public static class UserOperations
{
    public static decimal Average(IEnumerable<decimal> source)
    {
        return source.Average();
    }

    // Other methods
}


class Program
{
    static void Main(string[] args)
    {
        // The operation retrieved from the db
        string operation = "Average";
        // The items on which the operations should be performed
        decimal[] items = { 22m, 55m, 77m };

        object result = typeof(UserOperations).GetMethod(operation).Invoke(null, new object[] { items });
        Console.WriteLine(result);
        Console.ReadLine();
    }
}
于 2011-03-04T13:12:20.997 回答