我正在尝试设计客户端/服务器应用程序,它将能够交换"命令".事实是,该服务器应用程序正在处理一些东西,我希望客户端能够例如向服务器发送命令"pause".
经理建议,最好的方法是创建接口(例如ICommand),然后为将从ICommand继承的每个命令(暂停,恢复)分类.之后,我们可以简单地使用[DataContract]属性创建一个对象Pause,该对象将被发送到服务器.为此,我尝试使用共享类型,因此我创建了分离的程序集,在其中设计了所有[DataContracts],以便服务器和客户端都可以使用它们(它们具有指向它们的引用).
在服务器上,我们将有[OperationContract],它将[DataContract]作为参数并同样返回[DataContract],如下所示:
[ServiceKnownType(typeof(PauseServer))]
[ServiceKnownType(typeof(Resume))]
[ServiceContract]
public interface ITestService
{
[OperationContract]
ICommand DoCommand(ICommand command);
}
问题是,除了某些属性之外,我们还想使用例如"Execute(param1,param2)"方法,该方法将执行某些操作-该方法将在服务器上执行不同的操作(暂停进程),并在服务器上执行不同的操作客户端(例如,更改状态并启用"恢复"按钮).像这样:
[DataContract(Namespace="PauseContract")]
public class Pause
{
string _param1;
int _param2;
public void Execute()
{
// DO SOMETHING HERE
}
[DataMember]
public string Param1
{
get
{
return _param1;
}
set
{
this._param1 = value;
}
}
[DataMember]
public int Param2
{
get
{
return _param2;
}
set
{
this._param2 = value;
}
}
}
最后,整个过程将是这样的:1)客户希望暂停该过程,因此它创建了对象"Pause",其中将包含例如该过程的ID.2)该对象传递给DoCommand()方法,该方法在服务器端创建对象"Pause",并使用给定参数运行其"Execute()"方法.3)如果Pause进程结束得很好,Pause对象将返回给客户端(带有进程ID和其他属性)4)如果客户端收到此响应,它将知道该进程已经暂停并运行自己的"Execute()"方法在其自己的Pause对象上,这将更改GUI等.
所以我的问题是-是否有可能以不同的方式在服务器/客户端双方的公共库中存储合同的实现?还是这种方法通常是错误的?据我所知,不建议将行为(方法)包括在[DataContracts]中,但是我认为如果不使用[DataMember]属性对其进行标记,那就可以了.
谢谢你,雅库布.
老实说,我认为带有ServiceKnownType属性的ICommand不适用于命令.
ServiceKnownType旨在在类型属性而非行为的上下文中跨服务边界支持多态.
通过交换两个不同的请求/响应DataContract定义,可以非常轻松地实现您的"暂停/恢复"方案.
PauseResponse PauseProcessing(PauseCommand command);
在这种情况下,无需使事物通用I am trying to design client/server application, that would be able to exchange "commands". The thing is, that server application is processing some stuff and I would like the client to be able to for example send command "pause" to the server.
The thing is, that my manager suggested, that best approach would be to create interface (ICommand for example) and then class for each command (Pause, Resume) that would inherit from the ICommand. After that, we could simply create an object Pause with [DataContract] attribute, that would be sent over to server. For that purpouse, I tried to use shared-types, so I created seprated assembly in which I designed all the [DataContracts], so that both server and client can use them (they have reference leading to them).
On the server, we would then have [OperationContract], that would take the [DataContract] as parameter and return [DataContract] as well, like this:
[ServiceKnownType(typeof(PauseServer))]
[ServiceKnownType(typeof(Resume))]
[ServiceContract]
public interface ITestService
{
[OperationContract]
ICommand DoCommand(ICommand command);
}
The problem is, that apart from some properties, we would like to have for example method "Execute(param1,param2)", that would do certain operation - this method would do different operation on server (pause the process) and different operation on client side (change the status and enable "Resume" button for example). Like this:
[DataContract(Namespace="PauseContract")]
public class Pause
{
string _param1;
int _param2;
public void Execute()
{
// DO SOMETHING HERE
}
[DataMember]
public string Param1
{
get
{
return _param1;
}
set
{
this._param1 = value;
}
}
[DataMember]
public int Param2
{
get
{
return _param2;
}
set
{
this._param2 = value;
}
}
}
In the end, the whole process would like this: 1) Client wants to pause the process, so it creates object "Pause", that would contain for example ID of the process. 2) This object is passed to the DoCommand() method, which creates object "Pause" on server side and run its "Execute()" method with the given parameters. 3) If the Pausing process ended well, the Pause object is returned back to client (with process ID and other attributes) 4) If client gets this response, it will know that the process has eben paused and run its own "Execute()" method on its own Pause object, that would change the GUI and so on.
So my question is - is it somehow possible, to have different implementation of contracts stored in common library on both server/client side? Or is this approach wrong in general? From what I have heards, it is not advised to include behaviour (methods) to [DataContracts], but I thought it would be ok, if I dont mark them with [DataMember] attribute.
Thank You, Jakub.
To be honest, I don't think the ICommand with ServiceKnownType attribute idea works well for commands.
ServiceKnownType is designed to support polymorphism across service boundaries in the context of type properties and not behavior.
Your Pause/Resume scenario would be very easily implement with the exchange of two distinct request/response DataContract definitions.
PauseResponse PauseProcessing(PauseCommand command);
There is no need to make things generic in this instance本人是.net程序员,因为英语不行,使用工具翻译,希望对有需要的人有所帮助
如果本文质量不好,还请谅解,毕竟这些操作还是比较费时的,英语较好的可以看原文