我的老板让我看看计算引擎。实际上,用户将拥有一个可以进行计算的数据表。他们也将能够根据我们执行的某些限制来构建他们自己的计算(构建的计算将存储在数据库中)根据数据库中的数据动态调用C#方法
是否可以在C#中调用特定方法,具体取决于存储在数据库?所以如果数据库说,计算应该执行一个标准偏差。当我们从数据库中获取这些信息时,是否可以调用我们在C#中使用的标准偏差方法?
我希望这很清楚。
我的老板让我看看计算引擎。实际上,用户将拥有一个可以进行计算的数据表。他们也将能够根据我们执行的某些限制来构建他们自己的计算(构建的计算将存储在数据库中)根据数据库中的数据动态调用C#方法
是否可以在C#中调用特定方法,具体取决于存储在数据库?所以如果数据库说,计算应该执行一个标准偏差。当我们从数据库中获取这些信息时,是否可以调用我们在C#中使用的标准偏差方法?
我希望这很清楚。
考虑将你的数据,可进行操作的小型/已知量,我会选择到手工编码这些操作的基础上,从数据库中检索到的数据。对于可扩展性/可维护性,最好为此创建适当的设计,而不是使用简单的switch语句。我猜Strategy pattern将适合您的需求。
正如其他人所述,您可以使用使用reflection,以调用数据库中指定的方法。这种方法的问题是数据库中的数据与方法签名紧密相关。与第一种方法相比,这不太可维护,但只需最少的代码调整即可实现极大的可扩展性。另一个缺点是使用MethodInfo.Invoke()
比较慢。
如果你想选择思考,但发现Invoke()
方法太慢,我可以推荐this article by Jon Skeet,它解释了如何将MethodInfo转换为委托实例。这给了主要的速度提升。我最近写了a generic implementation using expression trees。
总之,看起来选项1仍然是最适合您的用途。
您可以使用C#中的switch语句根据来自数据库的记录字段(或标量)的值执行所需的操作。如果您的操作支持的操作数很少/数量有限,那么这是可以的,否则当然您可以使用reflection和MethodInfo类通过某个类的“字符串名称”调用成员方法。
我相信枚举(第一选项)更快更安全。什么会阻止某人将File.Delete()或其他讨厌的方法名称放入数据库中? – jonathanpeppers 2011-03-04 13:08:48
我同意,我没有考虑将运行时代码编译作为第二点,而是将其中的CalculationEngine方法名称考虑在内。 – 2011-03-04 13:10:44
您可以将操作存储在数据库中并使用Microsoft.CSharp.CSharpCodeProvider
即时编译代码。
见样本这里:Execute code at runtime
是的,这是可能的;它被称为反射,这是一个标准的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
我会建议你实施策略模式(http://www.dofactory.com/Patterns/PatternStrategy.aspx)
您可以加载需要不同的计算不同的策略(算法)。
是的,你可以使用反射做到这一点。您可以编写一个包含用户可以执行的所有操作的类,然后动态调用其方法。
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();
}
}
使用反射,有很多例子 – Stecya 2011-03-04 13:06:25
你可以将每个方法编码为一个整数并将其存储在数据库中,然后在该整数上执行切换,并在每种情况下调用相关方法? – 2011-03-04 13:07:07
你能更清楚地解释它吗?因为从你写的内容来看,我建议你只需从你的C#应用程序连接到数据库,然后在哪种情况下应该调用哪种方法来制定一些条件。或者,也许你想要别的东西? – Tobiasz 2011-03-04 13:07:32