2011-10-22 85 views
0

我創建了一個提供多種服務的應用程序。每個服務都提供了一種特定的處理能力,除了一個服務(即主服務),如果指定的處理能力可用,則向請求的客戶機返回真或假。如何區分通信和處理層?

現在我將修改應用程序,使主服務保持不變,併爲插件的安裝添加新的處理能力:每個插件都應該添加新的處理功能而無需實現新服務,但是在安裝新的插件,一個新的服務應該是可用的。通過這種方式,插件不應該處理通信層。換句話說,我想分開溝通層和處理層,以簡化新插件的創建。

可能嗎?

我可以創建兩個服務:主服務和處理服務。 客戶端可能會使用第一個服務來知道服務器上是否存在某個功能(例如,客戶端可能會詢問服務器是否安裝了提供解微分方程功能的插件)。 第二服務可以被用來發送一個通用的任務,並接收一般的結果,例如:

Result executeTask(Task task); 

其中結果任務是抽象類...

例如,如果我開發插件來解決微分方程,我首先創建用於傳送數據的類:

public class DifferentialEquationTask : Task 
// This class contains the data of the differential equation to be solved. 
... 

public class DifferentialEquationResult : Result 
// This class contains the the result. 
... 

因此,客戶端壽LD實例化一個新對象DifferentialEquationTask並將它傳遞給所述第二服務的方法,包括:

DifferentialEquationTask myTask = new DifferentialEquationTask(...); 
... 
Result result = executeTask(myTask); // called by basic application 
// The second service receives myTask as a Task object. 
// This Task object also contains the destination plugin, so myTask is send 
// to the correct plugin, which converts it to DifferentialEquationTask 
... 
myResult = result as DifferentialEquationResult; 
// received by the client 

此外,每個插件應該具有用於​​應用服務器和用於客戶機應用程序的一個版本的一個版本。

另一種方法是將服務包含在插件本身中:通過這種方式,新插件應實現新功能並通過附加服務公開它。 綜上所述,筆者認爲以下兩種選擇:

  1. 主要服務要求服務器,如果它有一個插件或沒有了,第二個服務以正確的插件交付的任務;
  2. 一個主要服務,詢問服務器是否有插件,以及各種附加服務(爲每個插件安裝附加服務)。

爲了選擇最好的方法,我可以用以下要求:

  • 這兩種選擇都可以提供更好的性能?
  • 使用每個插件的新服務,而不是使用在正確的插件上傳遞任務的單個服務,可以獲得哪些優勢?
  • 這兩個選擇中的哪一個簡化了新插件的開發?

作爲一個新手,我想知道是否有一個更好的辦法...

非常感謝!

+0

你試圖避免什麼「溝通層」的東西? WCF正在照顧「溝通層」。 –

+0

我想爲基礎應用程序創建新的插件不涉及到使用WCF:我希望通信只在基本應用程序上實現,而插件只應該添加新的處理功能。例如,如果我想創建一個解決微分方程的新插件,那麼我只會實現類,這樣我就可以解決這類方程,而無需在插件中實現新的服務。 – enzom83

+0

調用者將如何知道新函數存在?調用者將如何知道如何使用新功能?調用者如何知道如何將參數傳遞給新功能,以及通信層如何知道如何將參數傳遞給新功能?這些並不是新問題,一般來說,答案是「聽起來不錯,但實際上並沒有那麼好」。 –

回答

1

似乎主服務可以維護一個按名稱索引的插件字典。然後,爲了讓客戶端了解服務器是否提供了特定的服務,所有主要服務都要查找字典中的名稱。爲了處理,服務只需要調用字典條目的值部分中的對象的方法。示例:

您有三個抽象類:Service,ServiceResultServiceTaskServiceTaskServiceResult的內容對於本次討論並不重要。 Service必須有一個無參數的構造函數和一個名爲Process的方法,它將ServiceTask作爲其唯一參數。所以你的微分方程求解器看起來像:

public class DiffeqSolver : Service 
{ 
    public DiffeqSolver() 
    { 
     // do any required initialization here 
    } 

    public ServiceResult Process(ServiceTask task) 
    { 
     DiffeqTask dtask = task as DiffeqTask; 
     if (dtask == null) 
     { 
      // Error. User didn't pass a DiffeqTask. 
      // Somehow communicate error back to client. 
     } 

     // Here, solve the diff eq and return the result. 
    } 
} 

主要服務以某種方式通知現有的插件。它保留了字典:

Dictionary<string, Service> Services = new Dictionary<string, Service>(); 

我假設你有一些想法你要如何加載插件。你想要什麼,實際上是字典包含:

Key = "DiffeqSolver", Value = new DiffeqSolver(); 
Key = "ServiceType1", Value = new ServiceType1(); 
etc., etc. 

然後,您可以對主要服務兩種方法:ServiceIsSupportedProcess

bool ServiceIsSupported(string serviceName) 
{ 
    return Services.ContainsKey(serviceName); 
} 

ServiceResult Process(string serviceName, ServiceTask task) 
{ 
    Service srv; 
    if (Services.TryGetValue(serviceName, out srv)) 
    { 
     return srv.Process(task); 
    } 
    else 
    { 
     // The service isn't supported. 
     // Return a failure result 
     return FailedServiceResult; 
    } 
} 

我已經簡化,爲一些程度。特別是,我使用的不是線程安全的Dictionary。您想要使用ConcurrentDictionary,或使用鎖定來同步對詞典的訪問。

我認爲更困難的部分是加載插件。但是有很多創建插件體系結構的可用示例。我想你可以找到你需要的東西。

+0

是的,您的示例或多或少地反映了我認爲的解決方案!唯一的區別是,我想過使用兩個WCF服務(一個用來檢查某個插件是否受支持,另一個用於處理),但我想我會從你的例子中獲得靈感,實現一個WCF服務,方法是' ServiceIsSupported'和'Process'。非常感謝您的回覆! – enzom83

+0

使用單一服務的限制是什麼(即對於不同類型的處理使用單個方法「進程」)?使用這種可以通過使用多服務方法(每種處理類型的服務)可以消除的方法是否有缺點? – enzom83

+1

@ enzom83:如果您爲每種類型的處理都有單獨的服務,那麼無論何時添加新的插件,都必須添加新的服務。這使得添加一個插件更復雜一些。我沒有看到使用單個'Process'方法有什麼缺點,並且實現起來要容易得多。 –