我的老板让我调查计算引擎。实际上,用户将拥有可以进行计算的数据表。他们还可以根据我们强制执行的某些限制来构建自己的计算(然后将构建的计算存储在数据库中)
是否可以在C#中调用特定方法,具体取决于数据库中存储的内容?因此,如果数据库说,计算应执行标准偏差。当我们从数据库中获取信息时,是否可以调用C#中的标准偏差方法?
我希望这很清楚。
答案 0 :(得分:3)
考虑到将对您的数据执行的小/已知操作量,我会根据从数据库中检索到的数据选择手动编码这些操作。对于可扩展性/可维护性,最好为此创建一个合适的设计,而不是使用简单的switch语句。我猜Strategy pattern符合您的需求。
正如其他人所述,您可以使用reflection 来调用数据库中指定的方法。此方法的问题是数据库中的数据与方法签名密切相关。这比第一种方法的可维护性更低,但确实可以通过最少的代码调整实现极佳的可扩展性。另一个缺点是使用MethodInfo.Invoke()
相当慢。
如果您选择反射,但发现Invoke()
方法太慢,我可以推荐this article by Jon Skeet,它解释了如何将MethodInfo转换为委托实例。这提供了一个主要的速度提升。我最近为此写了a generic implementation using expression trees。
总而言之,选项1似乎仍然是最适合您的目的。
答案 1 :(得分: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
答案 2 :(得分:0)
您可以使用C#中的switch语句执行所需的操作,具体取决于来自数据库的记录字段(或标量)的值。如果你有少量/有限数量的受支持操作,这是可以的,否则你当然可以使用reflection和MethodInfo类来通过某个类的“字符串名称”调用成员方法。
答案 3 :(得分:0)
您可以在DB中存储操作,并使用Microsoft.CSharp.CSharpCodeProvider
即时编译代码。
请在此处查看示例:Execute code at runtime
答案 4 :(得分:0)
我建议您实施策略模式(http://www.dofactory.com/Patterns/PatternStrategy.aspx)
您可以为所需的不同计算加载不同的策略(算法)。
答案 5 :(得分:0)
是的,你可以使用Reflection做到这一点。您可以编写一个包含用户可以执行的所有操作的类,然后动态调用其方法。
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();
}
}