多分これはあなたを助けることができます。これらのクラスを使用して、リモートの AppDomains Trace.(Write/WriteLine) 呼び出しをリッスンできるようにします。
最初のクラスは、TraceListen の Write/WriteLine メソッドをカスタム デリゲートにリダイレクトできるようにするクラスです。
public delegate void TraceWriterHandler(string message);
internal class SynchronizedTraceListener : TraceListener
{
private TraceWriterHandler messageHandler;
public SynchronizedTraceListener(TraceWriterHandler writeHandler)
{
messageHandler = writeHandler;
}
public override void Write(string message)
{
messageHandler(message);
}
public override void WriteLine(string message)
{
messageHandler(message + System.Environment.NewLine);
}
}
次に、リモート AppDomain トレース リスナー クラスのコアです。これはトリッキーな部分です。説明をまちがえないようにします。これは私にはトリッキーですが、これで終わりです。
- (ローカル) CrossDomainTracer オブジェクトは、ファー AppDomain に (ファー) CrossDomainTracer オブジェクトを作成します。
- (ローカル) CrossDomainTracer オブジェクトは、(遠い) CrossDomainTracer オブジェクト .StartListening を呼び出し、参照としてそれ自身を (ローカル) 送信します。
- (far)CrossDomainTracer オブジェクトは、(far) 彼のドメインで Trace.Write/WriteLine 呼び出しのリッスンを開始します。
- (far)Trace.Write/WriteLine 呼び出しが行われると、(ローカル) リモート AppDomain から .RemoteWrite メソッドが呼び出されます。
- (ローカル) .RemoteWrite は、(ローカル) リスナーがメッセージを適切に表示できるように、独自の AppDomain スコープ Trace.Write を呼び出します。
ノート:
- AssemblyResolve は、このコードを含むアセンブリを参照しようとしたときにエラーを発生させます。
- このコードは両方のプロセスに存在し、同じ名前空間を共有する必要があります。ライブラリで使用し、アセンブリ参照を両方のアプリに追加します。
- また、Serializable 属性と MarshalByRefObject の継承にも注意してください。これは、フレームワークが AppDomain 間のオブジェクトのマーシャリングを適切に行うために必要です。
[Serializable]
public sealed class CrossDomainTracer : MarshalByRefObject
{
private CrossDomainTracer remoteTracer;
private SynchronizedTraceListener remoteListener;
public CrossDomainTracer()
{
}
public CrossDomainTracer(AppDomain farDomain)
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
this.remoteTracer = farDomain.CreateInstanceFrom(Assembly.GetExecutingAssembly().Location, typeof(CrossDomainTracer).FullName).Unwrap() as CrossDomainTracer;
AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler(CurrentDomain_AssemblyResolve);
if (remoteTracer != null)
{
remoteTracer.StartListening(this);
}
}
public void StartListening(CrossDomainTracer farTracer)
{
this.remoteTracer = farTracer;
this.remoteListener = new SynchronizedTraceListener(new TraceWriterHandler(Write));
Trace.Listeners.Add(this.remoteListener);
}
public void Write(string message)
{
this.remoteTracer.RemoteWrite("AppDomain(" + AppDomain.CurrentDomain.Id.ToString() +") " + message);
}
public void RemoteWrite(string message)
{
Trace.Write(message);
}
Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
try
{
Assembly assembly = System.Reflection.Assembly.Load(args.Name);
if (assembly != null)
{
return assembly;
}
}
catch { }
// Try to load by assembly fullname (path to file)
string[] Parts = args.Name.Split(',');
string File = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\" + Parts[0].Trim() + ".dll";
return System.Reflection.Assembly.LoadFrom(File);
}
}
最後に、これらすべてを静的クラスにきちんとまとめることができます。
public static class CrossDomainTrace
{
public static void StartListening(AppDomain remoteDomain)
{
new CrossDomainTracer(remoteDomain);
}
}
遠トレースのマッサージを登録するアプリでこれを行うことによって。
CrossDomainTrace.StartListening(theFarAppDomain);
あとは、TraceListner をこちら側の Trace.Listeners コレクションに追加して、メッセージに対して必要なことを行うだけです。
それが役に立てば幸い。