您能告诉我在 .net 3.5 中通过 NamedPipes 发送对象的最佳方式是什么吗?
6 回答
通过XmlSerializer序列化您的对象,而不是将其作为文本发送并在另一侧反序列化,或者按照 Remus 的建议使用 WCF 命名管道绑定
WCF NetNamedPipes 绑定是要走的路,你也可以考虑 .NET Remoting 来实现这个
在NetNamedPipeBinding上使用 WCF 。另请参阅通过命名管道绑定公开 WCF 服务。
您正在寻找的是 DataContract 属性。另请参阅:MSDN 使用数据协定。
数据契约是服务和客户端之间的正式协议,它抽象地描述了要交换的数据。也就是说,为了进行通信,客户端和服务不必共享相同的类型,只需相同的数据契约。数据契约为每个参数或返回类型精确定义了哪些数据被序列化(转换为 XML)以进行交换。
您的服务合同:
[ServiceContract]
public interface IApplicationRegistration
{
// Sends the application information
[OperationContract]
bool RegisterApplication(AppInfo appInfo);
}
要交换的数据:
[DataContract]
public class AppInfo
{
private int _processID;
private string _processName;
[DataMember]
public int ProcessID
{
get { return _processID; }
set { _processID = value; }
}
[DataMember]
public string ProcessName
{
get { return _processName; }
set { _processName= value; }
}
}
正如对原始问题的评论指出的那样,您不会将对象发送到其他进程。您可以将数据发送到另一个进程,并且该数据可用于在另一个进程中创建原始对象的代理或传真,但您不能直接发送对象。
即使是提供进程间对象传递语义的技术,在幕后也正是这样做的。因此,您应该始终使用“尝试执行操作,如果失败则捕获异常”的操作风格,而不是“确保可以执行操作然后执行它”的风格。即使对象看起来对您的操作而言它处于有效状态,但您正在查看旧数据,因此当您尝试执行实际操作时它可能无效。
所以,既然你不能发送对象,你最终要做的是序列化一些数据(使用 XmlSerializer 或 DataContractSerializer 或其他),在另一端读取数据流,并创建一个新对象代表旧的。您可能会发现创建一个单独的对象来表示您希望通过管道发送的数据比对象的实际、实时表示更容易。
WCF 可以自动为您处理很多此类内容,但您自己通过管道发送它并没有什么困难。
如果按照其他人的建议使用 WCF,请注意您仍然没有发送“对象”。您仍在发送数据,WCF 对此非常明确(这就是为什么他们称它为 DataContractSerializer,而不是 ObjectSerializer)。具体来说:
1) 对使用 DataContract 序列化发送的对象执行的任何操作都将在本地执行。
2) 如果同一个对象被发送两次,它不会自动更新它的任何旧版本,它们也不会有引用相等性。就 C# 而言,您将拥有两个完全不相关的数据结构。
3) 对一个对象的更新只会在本地执行,不会自动用“相同”的对象更新其他进程。
如果您绝对确信您需要跨进程传递“对象”,您可以自己滚动(我实际上建议这样做,即使它需要更多工作),或者使用 System.Remoting 命名空间。
即使使用 System.Remoting,也要意识到我上面谈到的就是实际发生的事情,并在设计对象和系统时牢记这一点。你会得到更好的结果。
使用我的一些代码;-)