我有两个进程(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:我想要的是一种不依赖于手动创建参数数组的解决方案;可以为我自动创建这个数组的东西。
答案 0 :(得分:0)
我最终使用RealProxy。 RealProxy主要用于远程处理,但可以允许您为类创建代理。然后,您可以在每次方法调用之前添加功能(也称为属性调用)。我用这个非常好的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 Api : MarshalByRefObject, IApi
{
public void Foo(SomeClass paramA, SomeOtherClass paramB)
{
}
public void Bar(SomeClassX paramA, SomeOtherClassY paramB)
{
}
}
}
另外,作为RealProxy的要求。该类必须继承MarshalByRefObject,这对我来说很好,因为它没有其他功能。在我链接的博客文章中阅读更多相关信息。