2012-01-01 46 views
1

因此,我正在考慮將我的業務操作(或者更確切地說,他們的名字)放到數據庫中,以便我可以將它們鏈接到用戶角色(用於授權),並設置通知系統運作。業務操作建模:將名稱鏈接到代碼

麻煩的主要問題是如何將數據庫中的操作(可能由字符串表示,如「Customer.New」或「Customer.View」)轉換爲在系統中運行的代碼。我提出的大多數方法似乎都很糟糕。

例1 - 一般的方法來處理所有操作

public static object RunOperation(string Op, string User, params object[] Parms) 
{ 
    switch(Op) 
    { 
     case "Customer.View": 
      return BLL.Facade.GetCustomerById((int)Parms[0]); 
      break; 
     case "Customer.New": 
      return BLL.Facade.CreateCustomer(Parms[0] as Customer); 
      break; 
     ... 
    } 
} 

我討厭這個事情是所有的鑄件。但授權很容易。 Authorize(Op, User);

然後是這樣:

[BusinessOp("Customer.New")] 
public static int CreateCustomer(Customer NewCustomer) 
{ 
    ... 
} 

但隨後授權是有點靠不住的,因爲我想我將不得不通過CreateCustomer方法引用到授權方法(和不同的OPS都會有不同的方法簽名)。然後,Authorize方法將不得不使用反射來查找BusinessOpAttribute並獲取操作的字符串名稱(它在數據庫中表示的方式)。

我想我可以做的另一件事是創建一系列表示操作的字符串名稱的常量,並將它們用於Authorize方法,但只需在執行操作時調用業務方法即可。但是,我仍然沒有一個項目(不管是方法還是字符串)代表所有各方的業務運作。

有沒有人有這方面的經驗,是否有另一種選擇,我沒有考慮?

ANSWER

最終通過與接受的答案意見決定。我會爲每項業務操作製作一堂課。例如:

[BusinessOperation] 
public static class CustomerNew 
{ 
    public const string Key = "Customer.New"; 

    public static bool Authorize(string UserName) // or perhaps IPrincipal User 
    { 
     // Authorize method will use key to check against database 
     ... 
    } 

    public static int Invoke(Customer NewCustomer) 
    { 
     // Invoke method has well-defined parameters 
     ... 
     // Can also use key to notify listeners of operation completion 
    } 
} 

回答

0

我們處理類似問題的方式是讓實際操作代表指定類上的具體方法。其中最大的問題是params,我們總是留給實施方法來處理。

所以你的情況,我會重構類似於:

var asValues = Op.Split('.'); 

switch(asValues[0].ToLower()) 
{ 

    case "customer": 
     Type type = typeof(BLL.CustomerFacade); 

     System.Reflection.MethodInfo method = type.GetMethod(asValues[1], System.Reflection.BindingFlags.IgnoreCase); 

     if (method != null) 
     { 
      return method.Invoke(BLL.CustomerFacade, Parms); 
     } 
     break; 

注意,我改變了外立面爲CustomerFacade並在此爲CustomerFacade的GetCustomerById將變爲查看。這只是解決這個問題的一種方法。例如,您也可以將所有內容保存在一個外觀中,並將方法名稱更改爲CustomerView。此外,如果還有其他代碼片段依賴於現有外觀名稱,則可以更改操作名稱或添加重定向方法,以將請求重定向到正確的底層外觀方法。

這可能需要根據你的實現進行一些調整,但它應該給你一個總體思路。

這種方法的好處是,您不必每次都需要更新此方法來實施新操作。

+0

謝謝你的回答。這不是我想要的解決方案,因爲調用方法仍然需要知道它調用的方法的內部細節(確切地知道要傳遞哪些參數),違反了封裝原則。但是,如果我找不到更好的解決方案,我最終可能會這樣做。 – 2012-01-01 21:43:13

+0

@ KaseySpeakman:我同意,這是雞和雞蛋的情況。但是,您可以通過檢查方法參數來反轉控制,然後向調用者請求適當的值。例如,您可以添加一個ValueFetch接口,例如,該接口將由調用者實現,並將基於其名稱或使用反射爲參數提供值(假定實現類將具有存儲在屬性中的值)。然後您只需傳遞實現實例而不是參數數組。 – 2012-01-01 21:55:34

+0

我正在考慮爲擁有Authorize和Invoke方法的每個業務操作一個類,以及一個作爲操作的數據庫名稱的const Key。 Authorize方法將使用該鍵來授權操作,但Invoke方法將具有明確定義的參數。這是額外的工作,但它確實避免了反思。思考? – 2012-01-01 22:18:51