如何分离通信和处理层?

时间:2011-10-22 13:58:44

标签: c# wcf

我创建了一个提供多种服务的应用程序。每个服务都提供特定的处理功能,但一个服务(即主服务)向客户端返回true或false,如果指定的处理能力可用,则请求客户端。

现在我将修改应用程序,保持主服务不变,并添加对具有新处理功能的插件安装的支持:每个插件都应添加新的处理功能,而无需实现新服务,但在安装新服务之后插件,应该提供新的服务。这样,插件不应该处理通信层。换句话说,我想将通信和处理层分开,以简化新插件的创建。

有可能吗?

我可以创建两个服务:主服务和处理服务。 客户端可以使用第一服务来知道服务器上是否存在某个特征(例如,客户端可以询问服务器是否已经安装了提供解决微分方程的功能的插件)。 第二个服务可用于发送通用任务并接收一般结果,例如:

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.
...

因此,客户端应该实例化一个新的对象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. 要求服务器是否有插件的主要服务,以及各种附加服务(安装每个插件的附加服务)。
  3. 为了选择最佳方法,我可以使用以下要求:

    • 两种替代方案中的哪一种可以提供更好的性能?
    • 使用每个插件的新服务比使用以正确插件提供任务的单个服务有什么好处?
    • 这两种选择中的哪一种简化了新插件的开发?

    作为一个新手,我想知道是否有更好的方法......

    非常感谢!

1 个答案:

答案 0 :(得分:1)

似乎主服务可以维护一个按名称索引的插件字典。然后,对于客户端来查看服务器是否提供特定服务,所有主要服务所要做的就是在字典中查找名称。要处理,服务只需要在字典条目的值部分中的对象上调用方法。一个例子:

您有三个抽象类:ServiceServiceResultServiceTaskServiceTaskServiceResult的内容对于此讨论并不重要。 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,或使用锁定来同步对字典的访问。

我认为,更难的部分是加载插件。但是有很多可用的创建插件架构的例子。我想你可以找到你需要的东西。