我的老闆讓我看看計算引擎。實際上,用戶將擁有一個可以進行計算的數據表。他們也將能夠根據我們執行的某些限制來構建他們自己的計算(構建的計算將存儲在數據庫中)根據數據庫中的數據動態調用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