2

我正在编写一个 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)?

对不起,愚蠢的问题,并在此先感谢。

4

2 回答 2

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 远程处理充满了有趣的惊喜和不眠之夜。为了解决这个问题,请让自己熟悉远程处理概念(从我的角度来看,这些概念记录得很差)。深入研究序列化概念(MarshalByRefObjectvs. [Serializable])。如果您想从中制作生产代码,请考虑一种处理远程异常的非常好的方法。还要考虑多线程。一次可能有多个客户端使用此远程对象。

玩得开心!

于 2009-01-20T23:14:09.010 回答
0

谢谢!我非常感谢您回答的彻底和清晰。

最奇怪的是我什至不知道你可以发布对象实例。我研究过的大约十几个简单的教程被提议RemotingConfiguration.RegisterWellKnownServiceType作为进行远程处理的唯一方法。愚蠢的我。

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

于 2009-01-21T02:51:17.620 回答