リモート インターフェイスで呼び出しメソッドを使用するカスタム ジェネリック クラスがあります。このクラスには、単一のオーバーロードされたメソッドがあり、リモート インターフェイスで呼び出すorExecute
を受け入れます。Action<T>
Func<T, TResult>
public class GenericRemoteProxy<T>
{
public void Execute(Action<T> action) {
// Remoting Magic Goes Here
}
public TResult Execute<TResult>(Func<T, TResult> action) {
// Remoting Magic Goes Here
}
}
クラスの使用は非常に簡単です。
var proxy = new GenericRemoteProxy<ICalculatorService>();
var result = proxy.Execute(x => x.Add(1, 2));
ただし、これをさらに一歩進めてGenericRemoteProxy
、実際のサービス コントラクト インターフェイスを実装するクラスでラップし、クライアント コードが関心のある実際のインターフェイスのみに依存するようにしたいと考えています。ChannelFactory
これは、WCFの とまったく同じ動作になります。.NET 4.0 でこれを行うためのネイティブな方法はないようです。そのため、代わりに Castle Dynamic Proxy を使用してそれを達成しようとしています。
Actions
どのタイプの DynamicProxy を使用する必要があるか、また、ターゲット インターフェイスからの呼び出しをどのように正確に変換し、Funcs
それを に渡すことができるかを正確に把握するのに少し苦労していGenericRemoteProxy
ます。
私の現在のアプローチは、カスタムを使用しProxyGenerator
てマッピングを処理することです。CreateInterfaceProxyWithoutTarget
IInterceptor
var calculatorService =
proxyGenerator.CreateInterfaceProxyWithoutTarget<ICalculatorService>(
new GenericProxyInterceptor<ICalculatorService>(
new GenericRemoteProxy<ICalculatorService>()));
次に、インターセプターは次のようになります。
public class GenericProxyInterceptor<T> : IInterceptor {
GenericRemoteProxy<T> _proxy;
public GenericProxyInterceptor(GenericRemoteProxy<T> proxy) {
_proxy = proxy;
}
public void Intercept(IInvocation invocation) {
var instance = Expression.Parameter(typeof(T), "x");
var arguments = invocation.Arguments.Select(x => Expression.Constant(x));
var methodCall = Expression.Call(instance, invocation.Method, arguments);
var lambda = Expression.Lambda(methodCall, instance);
if (invocation.Method.ReturnType == typeof(void)) {
var action = //Create an Action
_proxy.Execute(action);
} else {
var action = //Create a Func
_proxy.Execute(action);
}
}
}
私の最初の質問は、Castle Dynamic Proxy で私が求めていることを達成するための正しいアプローチですか? そうでない場合、インターフェイスへの呼び出しをまったく異なるタイプのメソッドにどのようにマッピングする必要がありますか? Dynamic Proxy を誤って使用すると、メモリと CPU が過剰に使用される可能性があることを読んだので、可能であればそれを避けたいと思います。
2 番目の質問は、LINQ 式を正しいものAction<T>
、またはFunc<T, TResult>
プロキシが期待するものに変換するにはどうすればよいですか? デバッグ ビューでは、ラムダは正しいように見えます (として表示されますx => x.Add(1,2)
)。lambda.Compile()
しかし、メソッドに渡そうとするとExecute
、メソッドに無効な引数があると言われます。