2011-03-04 73 views
5

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

是否可以在C#中調用特定方法,具體取決於存儲在數據庫?所以如果數據庫說,計算應該執行一個標準偏差。當我們從數據庫中獲取這些信息時,是否可以調用我們在C#中使用的標準偏差方法?

我希望這很清楚。

+0

使用反射,有很多例子 – Stecya 2011-03-04 13:06:25

+0

你可以將每個方法編碼爲一個整數並將其存儲在數據庫中,然後在該整數上執行切換,並在每種情況下調用相關方法? – 2011-03-04 13:07:07

+2

你能更清楚地解釋它嗎?因爲從你寫的內容來看,我建議你只需從你的C#應用​​程序連接到數據庫,然後在哪種情況下應該調用哪種方法來制定一些條件。或者,也許你想要別的東西? – Tobiasz 2011-03-04 13:07:32

回答

3

考慮將你的數據,可進行操作的小型/已知量,我會選擇到手工編碼這些操作的基礎上,從數據庫中檢索到的數據。對於可擴展性/可維護性,最好爲此創建適當的設計,而不是使用簡單的switch語句。我猜Strategy pattern將適合您的需求。

正如其他人所述,您可以使用使用reflection,以調用數據庫中指定的方法。這種方法的問題是數據庫中的數據與方法簽名緊密相關。與第一種方法相比,這不太可維護,但只需最少的代碼調整即可實現極大的可擴展性。另一個缺點是使用MethodInfo.Invoke()比較慢。

如果你想選擇思考,但發現Invoke()方法太慢,我可以推薦this article by Jon Skeet,它解釋瞭如何將MethodInfo轉換爲委託實例。這給了主要的速度提升。我最近寫了a generic implementation using expression trees

總之,看起來選項1仍然是最適合您的用途。

0

您可以使用C#中的switch語句根據來自數據庫的記錄字段(或標量)的值執行所需的操作。如果您的操作支持的操作數很少/數量有限,那麼這是可以的,否則當然您可以使用reflection和MethodInfo類通過某個類的「字符串名稱」調用成員方法。

+0

我相信枚舉(第一選項)更快更安全。什麼會阻止某人將File.Delete()或其他討厭的方法名稱放入數據庫中? – jonathanpeppers 2011-03-04 13:08:48

+0

我同意,我沒有考慮將運行時代碼編譯作爲第二點,而是將其中的CalculationEngine方法名稱考慮在內。 – 2011-03-04 13:10:44

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

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