如何将通信层和处理层分开
本文关键字:处理 通信 | 更新日期: 2023-09-27 18:12:09
我创建了一个提供多种服务的应用程序。每个服务提供一个特定的处理能力,除了一个服务(即主服务),它向请求指定处理能力是否可用的客户端返回true或false。
现在我将修改应用程序,保持主服务不变,并增加对安装具有新处理能力的插件的支持:每个插件都应该添加新的处理能力,而不需要实现新的服务,但安装新插件后,应该有新的服务可用。这样,插件就不应该处理通信层。换句话说,我希望将通信层和处理层分开,以简化新插件的创建。
有可能吗?
我可以创建两个服务:主服务和处理服务。第一个服务可能被客户端用来了解服务器上是否存在某个功能(例如,客户端可能会询问服务器是否安装了提供求解微分方程功能的插件)。第二个服务可用于发送一般任务并接收一般结果,例如:
Result executeTask(Task task);
其中Result和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.
...
因此,客户端应该实例化一个新对象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
此外,每个插件应该有一个应用服务器的版本和一个客户端应用程序的版本。
另一种选择是将服务包含在插件本身中:这样,一个新插件应该实现一个新功能,并通过一个额外的服务公开它。总之,我认为有以下两种选择:
- 一个主服务询问服务器是否有插件,第二个服务在正确的插件上交付任务;
- 一个主服务,询问服务器是否有插件,以及各种附加服务(每个插件安装一个附加服务)。
为了选择最好的方法,我可以使用以下要求:
- 两个备选方案中哪一个可以提供更好的性能?
- 为每个插件使用一个新服务比在正确的插件上使用一个单独的服务提供任务有什么好处?
- 这两个选项中哪一个简化了新插件的开发?
作为一个新手,我想知道是否有更好的方法…
非常感谢!
似乎主服务可以维护一个插件字典,按名称索引。然后,客户端要查看服务器是否提供特定的服务,主服务所要做的就是在字典中查找名称。要处理,服务只需要调用字典条目值部分中的对象的方法。一个例子:
您有三个抽象类:Service
, ServiceResult
和ServiceTask
。ServiceTask
和ServiceResult
的内容在本文中并不重要。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.
主服务可以有两个方法:ServiceIsSupported
和Process
:
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
,或者使用锁来同步对字典的访问。
更困难的部分,我认为,将加载插件。但是有很多创建插件架构的例子。我想你能找到你需要的。