我正在编写一个Windows服务应用程序,它将通过.NET Remoting访问。 问题是我无法弄清楚如何从远程类访问服务对象。
例如,我有一个处理程序类:
class Service_console_handler
{
public int something_more = 20;
//some code...
TcpChannel serverChannel = new TcpChannel(9090);
ChannelServices.RegisterChannel(serverChannel);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(RemoteObject), "RemoteObject.rem",
WellKnownObjectMode.Singleton);
//from here on RemoteObject is accessible by clients.
//some more code doing something and preparing the data...
}
我有一个远程班级:
public class RemoteObject : MarshalByRefObject
{
private int something = 10;
public int Get_something()
{
return something;
}
}
客户端可以毫无问题地访问RemoteObect中的数据。但是如何访问Service_console_handler
对象(即从something_more
中检索有用信息)?
对于愚蠢的问题表示歉意,并提前致谢。
答案 0 :(得分:6)
您想要的是以某种方式通过ServiceConsoleHandler
实例访问RemoteObject
的实例,该实例对客户端可见。
为此,您需要考虑两件事:(1)控制RemoteObject
实例的对象构造并使其可访问;(2)修改ServiceConsoleHandler
以便远程访问它。
如果您不需要考虑远程处理,如何在RemoteObject
中构建ServiceConsoleHandler
实例?
我想你会做这样的事情:
class ServiceConsoleHandler
{
…
RemoteObject remoteObject = new RemoteObject();
// now assume that you also already have
// modified the RemoteObject class so it can hold
// a reference to your server:
remoteObject.Server = this;
…
}
如果您可以为客户端访问此对象,那将是很好的。您可以使用RemotingServices.Marshal代替RemotingConfiguration.RegisterWellKnownServiceType执行此操作:
class ServiceConsoleHandler
{
…
TcpServerChannel channel = new TcpServerChannel(9090);
ChannelServices.RegisterChannel(channel, true);
RemoteObject remoteObject = new RemoteObject();
remoteObject.Server = this;
RemotingServices.Marshal(remoteObject, "RemoteObject.rem");
…
}
如果您现在执行代码并访问客户端代码中的remoteObject.Server
,您将获得一些远程处理异常,因为无法远程访问类ServiceConsoleHandler
。因此,您需要添加[Serializable]
属性:
[Serializable]
class ServiceConsoleHandler
{ … }
原因:应远程访问的类型需要封送到某些特殊的可转移表示。这样,它们可以通过TCP端口挤压并通过TCP协议传输。基本数据类型可以由框架编组,因此您无需考虑它们。对于自定义类型,您需要说明,如何执行此操作。一种方法是通过MarshalByRefObject
的子类化。这正是您已经使用RemoteObject
所做的。另一种方法是将自定义类标记为[Serializable]
,如上所示。
就是这样。现在,您应该能够访问客户端代码中的服务器字段。请注意,您不需要现有的代码激活代码:
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel, true);
RemoteObject remoteObject = (RemoteObject)Activator.GetObject(
typeof(RemoteObject), "tcp://localhost:9090/RemoteObject.rem");
Console.WriteLine(remoteObject.Server.SomethingMore);
对我来说,.NET远程处理充满了有趣的惊喜和不眠之夜。为了解决这个问题,请熟悉远程处理概念(从我的观点来看,这些概念很难记录)。深入了解序列化概念(MarshalByRefObject
与[Serializable]
)。如果您想从中制作生产代码,请考虑一种处理远程异常的非常好的方法。还要考虑多线程。可能会有多个客户端同时使用此远程对象。
玩得开心!
答案 1 :(得分:0)
谢谢!我非常感谢你回答的彻底性和清晰度。
大多数奇怪的事情是我甚至不知道你可以发布对象实例。我研究了大约十几个简单的教程RemotingConfiguration.RegisterWellKnownServiceType
作为远程处理的唯一方法。愚蠢的我。
现在远程处理对我来说看起来更有用。我刚刚写了一个快速测试应用程序,它工作。再次感谢。