.NET Remoting:如何从远程对象访问服务器应用程序对象?

时间:2009-01-19 05:39:33

标签: c# .net remoting

我正在编写一个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中检索有用信息)?

对于愚蠢的问题表示歉意,并提前致谢。

2 个答案:

答案 0 :(得分:6)

您想要的是以某种方式通过ServiceConsoleHandler实例访问RemoteObject的实例,该实例对客户端可见。

为此,您需要考虑两件事:(1)控制RemoteObject实例的对象构造并使其可访问;(2)修改ServiceConsoleHandler以便远程访问它。

(1)

如果您不需要考虑远程处理,如何在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");
     …
}

(2)

如果您现在执行代码并访问客户端代码中的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作为远程处理的唯一方法。愚蠢的我。

现在远程处理对我来说看起来更有用。我刚刚写了一个快速测试应用程序,它工作。再次感谢。