using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System;


namespace Echo
{
    class EchoProxy:RealProxy
    {
        EchoClass realObject = new EchoClass();

        public EchoProxy()
          : base(typeof(EchoClass)) // 透過プロキシのインタフェースを指定
        {
        }

        // プロキシがメッセージを受け取った時に呼ばれるメソッド。
        // ここで好きな処理を噛ませることができる。
        public override IMessage Invoke(IMessage msg)
        {
            IMethodMessage method = msg as IMethodMessage;

            Console.WriteLine("--- Start {0} ---", method.MethodName);
            try
            {
                // 3. 代理ではない本当の(?)オブジェクトのメソッド実行
                MethodInfo methodInfo = (MethodInfo)method.MethodBase;
                methodInfo.Invoke(realObject, method.Args);
            }
            catch (TargetInvocationException ex)
            {
                // 6. Echo内部で例外が発生すると
                // TargetInvocationExceptionが送出される。
                // Echo内部で発生した例外は ex.InnerException で取得。
                // ※Throw ex; だとスタックトレースが消える為
                //   例外は必ずReturnMessageで返すこと。
                return new ReturnMessage(ex.InnerException, (IMethodCallMessage)msg);
            }
            finally
            {
                Console.WriteLine("--- End {0} ---", method.MethodName);
            }

            // 4. 戻り値。今回のEchoには戻り値も出力も無いので、null, null 指定
            return new ReturnMessage(
              null, null, 0, method.LogicalCallContext, (IMethodCallMessage)msg);
        }
    }
}
