C# 以泛型方式调用使用反射的方法

C# Invoking a method using reflection in a generic manner

我有两个进程(A 和 B),都有一个方法 Foo(SomeClass paramA, SomeOtherClass paramB)。 进程使用 Windows 管道(不是 WCF)进行通信,并且可以发送和接收类型的消息:

public class PipeMessageArgs
{
     public PipeMessageArgs(string i_MethodName, List<object> i_Args)
      {
          MethodName = i_MethodName;
          Args = i_Args;
      }

      public string MethodName { get; private set; }
      public List<object> Args { get; private set; }
}

在 A 上调用 Foo 时,我想在 B 上调用 Foo,具有相同的值。

这是A中的调用代码:

public void Foo(SomeClass paramA, SomeOtherClass paramB)
{
    var args = new List<object> { paramA, paramB };
    m_Server.PushMessage(new PipeMessageArgs(MethodBase.GetCurrentMethod().Name, args));
}

这是B:

中的调用代码
void ClientOnReceiveMessage(NamedPipeConnection i_Connection, object i_Message)
{
    var pipeMessageArgs = i_Message as PipeMessageArgs;
    GetType().GetMethod(pipeMessageArgs.MethodName).Invoke(this, pipeMessageArgs.Args.ToArray());
}

但是如您所见,我必须为每次调用手动创建一个参数列表,因此如果我忘记了某个参数或弄错了顺序,事情将无法进行。鉴于我不能使用反射来获取值,并且我不想使用探查器(性能是一个问题),使它更通用的最佳方法是什么?

编辑:由于太多原因我无法使用 WCF(实际上,我正在远离 WCF)。我正在使用管道,即 PipeStream。

Edit2:我想要的是一个不依赖手动创建参数数组的解决方案;可以为我自动创建这个数组的东西。

我最终使用 RealProxy. RealProxy is mainly used for remoting but can allow you to create proxy for classes. You can then add functionality before each method call (also properties calls). I used this very nice blog post 来实现它。

这是我的代理:

public class InvokingProxy : RealProxy
    {
        private readonly INamedPipe _namedPipe;

        InvokingProxy(object i_Target, INamedPipe i_NamedPipe) : base(i_Target.GetType())
        {
            _namedPipe = i_NamedPipe;
        }

        public override IMessage Invoke(IMessage i_Msg)
        {
            var methodCall = i_Msg as IMethodCallMessage;

            if (methodCall != null)
            {
                return HandleMethodCall(methodCall);
            }

            return null;
        }

        IMessage HandleMethodCall(IMethodCallMessage i_MethodCall)
        {
            _namedPipe.PushMessage(new PipeMessageArgs(i_MethodCall.MethodName, i_MethodCall.InArgs));
            return new ReturnMessage(null, null, 0, i_MethodCall.LogicalCallContext, i_MethodCall);
        }

        public static T Wrap<T>(T i_Target, INamedPipe i_NamedPipe) where T : MarshalByRefObject
        {
            return (T)new InvokingProxy(i_Target, i_NamedPipe).GetTransparentProxy();
        }
    }

我使用 i_MethodCall.InArgs 来获取参数,这就是问题所在。还要注意 HandleMethodCall 如何使用管道推送消息而不是实际调用请求的方法。这意味着我的 'API' class 实际上只是没有实现的空方法(我总是可以在那里添加更多实现并调用方法 before/after 管道操作):

class Api : MarshalByRefObject, IApi
    {
        public void Foo(SomeClass paramA, SomeOtherClass paramB)
        {
        }

        public void Bar(SomeClassX paramA, SomeOtherClassY paramB)
        {
        }
    }
}

此外,作为 RealProxy 的要求。 class 必须从 MarshalByRefObject 继承,这对我来说很好,因为它没有其他功能。在我链接的博客 post 中阅读更多相关信息。