2011-10-22 86 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'方法有什么缺点,并且实现起来要容易得多。 –