1

MarshalByReferenceObjectそのメソッドは .net リモート処理を介して呼び出されます。

public class MyServer : MarshalByReferenceObject
{
    public void DoSomething();
}

System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownServiceType(
            typeof(MyServer), "serverUrl", System.Runtime.Remoting.WellKnownObjectMode.SingleCall);

クライアントは次のようにサーバーを呼び出しています。

var server = Activator.GetObject(typeof(MyServer), "serverUrl");
server.DoSomething();

デバッグの目的で、クライアントが DoSomething() メソッドを呼び出したときに、実際の呼び出し元が誰であるかをログに記録したいと思います。

server.DoSomething() 関数内から呼び出し元のメソッドを特定するにはどうすればよいですか? または、Activator.GetObject によって呼び出されるサーバー コンストラクター内からですか?

理想的には、どのクライアント メソッドがサーバーを呼び出したか、どの親メソッドがそのクライアント メソッドを呼び出したかなど、スタック トレース全体が必要です。しかし、私はある種の発信者識別に落ち着くでしょう。クライアントは私が管理しているので、どうにかして名前を付けることができますか? インターフェイスの仕様はすでにかなり決まっているので、そうでなければ余分なstring callerIdパラメーターをすべてのメソッドに追加することは避けたいと思います。

もちろん、ローカル スタック トレースはSystem.Runtime.Remotingメソッドのみを識別し、実際のリモート呼び出し元は識別しません。


サーバー側のスタックトレースの例:

    at MyServer.MyServer(), line 123
    at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
    at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache)
    at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache)
    at System.Activator.CreateInstance(Type type, Boolean nonPublic)
    [...] 
    at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

これは明らかに、クライアントからの呼び出しメソッドを識別するのに役立ちません。

4

1 に答える 1

2

クライアントとサーバーの動作を少し調整するオプションがある場合は、パラメーターをプロトコル クラス ( MyServer) コンストラクターに渡すことができます。

RemotingConfiguration.RegisterActivatedServiceTypeサーバー側では、プロトコル クラスの登録に使用できます。

クライアント側RemotingConfiguration.RegisterActivatedClientTypeでは、プロトコル クラスのインスタンスをサーバー上に作成することを登録するために呼び出すことができます。次に、新しいインスタンスを作成し、好きなクライアント識別パラメーターをコンストラクターに渡すだけで (通常の方法で、 を使用せずにActivator.GetObject)、オブジェクトがサーバー上で自動的に作成され、ローカルでプロキシされます。

プロトコル クラス

using System;

public class MyServer : MarshalByRefObject
{
    Guid clientID;

    public MyServer(Guid clientID)
    {
        this.clientID = clientID;
    }

    public void DoSomething()
    {
        Console.WriteLine("Logged operation from client {0}.", this.clientID);
    }
}

サーバ

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

class Server
{
    static void Main(string[] args)
    {
        ChannelServices.RegisterChannel(new TcpServerChannel(1234), false);
        RemotingConfiguration.ApplicationName = "Test";
        RemotingConfiguration.RegisterActivatedServiceType(typeof(MyServer));
        Console.WriteLine("Server listening ...");
        Console.ReadLine();
    }
}

クライアント

using System;
using System.Runtime.Remoting;

class Client
{
    static void Main(string[] args)
    {
        RemotingConfiguration.RegisterActivatedClientType(typeof(MyServer),
                                      "tcp://localhost:1234/Test");
        var id = Guid.NewGuid();
        Console.WriteLine("Creating object with id {0}.", id);
        var obj = new MyServer(id);
        obj.DoSomething();
    }
}
于 2015-03-09T00:33:54.403 に答える