0

サービスからの重要なメッセージをユーザーに表示するヘルパー アプリケーションに文字列を送り込む必要があるサービスがあります (Vista+ ではサービスに GUI へのアクセスを許可しません)。私は TCP 経由で .NET Remoting を使用したので、IPC プロトコルでも同じことを行うことにしました。ただし、リモート オブジェクトへの参照を取得した後、リモート メソッドを呼び出すと、次の例外が発生します。

MissingMethodException: No parameterless constructor defined for this object.

クラスにパラメーターなしのコンストラクターを追加するだけで、代わりに呼び出しを行うときに NullReferenceException が発生します。私が間違っているのは何ですか?関連するコードを以下に含めました。

アプリケーションコード

public class MyMsgBus : MarshalByRefObject, IDisposable, IMxServeBus
{
    private Thread myThread = null;
    private volatile List<string> myMsgBus = null;
    private volatile bool myThreadAlive = false;
    private volatile bool myIsDisposed = false;
    private volatile bool myIsDisposing = false;
    private IpcChannel myIpc = null;

    public MyMsgBus(string busname)
    {
       myMsgBus = new List<string>();

       myIpc = CreateIpcChannel(busname);
       ChannelServices.RegisterChannel(myIpc);

       var entry = new WellKnownServiceTypeEntry(
          typeof(MxServeBus),
          "MyRemoteObj.rem",
          WellKnownObjectMode.Singleton);

       RemotingConfiguration.RegisterWellKnownServiceType(entry);
    }

    // defined in IMyMsgBus
    public void SendMessage(string message)
    {
       // do stuff
    }

    public static IpcChannel CreateIpcChannel(string portName)
    {
       var serverSinkProvider = new BinaryServerFormatterSinkProvider();
       serverSinkProvider.TypeFilterLevel = TypeFilterLevel.Low;

       IDictionary props = new Hashtable();
       props["portName"] = portName;
       props["authorizedGroup"] = "Authenticated Users";

       return new IpcChannel(props, null, serverSinkProvider);
    }

    public static IpcChannel CreateIpcChannelWithUniquePortName()
    {
       return CreateIpcChannel(Guid.NewGuid().ToString());
    }
}

テスト クライアント

static void Main(string[] args)
{
   var channel = MyMsgBus.CreateIpcChannelWithUniquePortName();
   ChannelServices.RegisterChannel(channel, true);

   var objUri = "ipc://MyMsgBus/MyRemoteObj.rem";
   IMyMsgBus lBus = (IMyMsgBus)Activator.GetObject(typeof(IMyMsgBus), objUri);
   lBus.SendMessage("test");
   Console.WriteLine();
}

これについてご支援いただきありがとうございます。参考までに、これは IMyMsgBus が IPC 経由で呼び出すために使用できるメソッドを定義する共有インターフェイスを使用して構成されたリモート インスタンスです。

4

1 に答える 1

0

NullReferenceException適切な初期化にはパラメーターが必要であるため、パラメーターなしのコンストラクターを追加しています。これを指定しないと、初期化の一部が失われます。

パラメーターのないコンストラクターを次のように許可するようにコードをリファクタリングする必要があります。

   private bool _initialized = false;

    public MyMsgBus() {}

    public Initialize(string busname) // Make this part of interface    
    {
       myMsgBus = new List<string>();

       myIpc = CreateIpcChannel(busname);
       ChannelServices.RegisterChannel(myIpc);

       var entry = new WellKnownServiceTypeEntry(
          typeof(MxServeBus),
          "MyRemoteObj.rem",
          WellKnownObjectMode.Singleton);

       RemotingConfiguration.RegisterWellKnownServiceType(entry);
       _initialized = true;
    }

他のすべてのパブリック メソッドでは、_initializedフラグを確認しthrow NotInitializedException、フラグが false かどうかを確認します。

として使用する必要があります

 IMyMsgBus lBus = (IMyMsgBus)Activator.GetObject(typeof(IMyMsgBus));
 lBus.Initialize(objUri);
 ... do Further operation
于 2013-01-10T15:23:47.163 に答える