2

.NET Remoting を介してアクセスされる Windows サービス アプリケーションを作成しています。問題は、リモート可能なクラスからサービス オブジェクトにアクセスする方法がわからないことです。

たとえば、ハンドラー クラスがあります。

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

このためには、2 つのことを考慮する必要があります。(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;
   …
}

クライアントがこのオブジェクトにアクセスできるようにするとよいでしょう。これを行うには、RemotingConfiguration.RegisterWellKnownServiceType の代わりに RemotingServices.Marshal を使用します

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 プロトコルを介して転送できます。基本的なデータ型はフレームワークによってマーシャリングできるため、それらについて考える必要はありません。カスタムタイプについては、これを行う方法を述べる必要があります。これを行う 1 つの方法は、からサブクラス化することMarshalByRefObjectです。それはまさにあなたがすでに行ったことですRemoteObject。もう 1 つの方法は、[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

ありがとうございました!あなたの答えの徹底的さと明快さにとても感謝しています。

最も奇妙なことは、オブジェクト インスタンスを公開できることさえ知らなかったことです。私が研究した約 12 の簡単なチュートリアルRemotingConfiguration.RegisterWellKnownServiceTypeは、リモート処理を行う唯一の方法として提案されました。愚かな私。

今では、リモーティングがはるかに便利に思えます。簡単なテストアプリケーションを書いたところ、うまくいきました。再度、感謝します。

于 2009-01-21T02:51:17.620 に答える