【.NET Framework】リアルProxyと透過Proxy
- 2012.12.11 Tuesday
- 21:36
JUGEMテーマ:コンピュータ
Source and Project
何度か調べた事があるのに、透過Proxyという言葉を私は、正しく理解していなかったようです。現状の理解では、利用する側、つまりクライアントが、Proxyを利用していると意識せずに利用されるProxyの事を、透過Proxyというのだと思っています。意識しないとは、Proxyを利用する為の決まった手続きをしないという事であって、調べてそれがProxyであるかどうか判定できないという意味ではないです。
Don Box著の「Essential .NET」に透過Proxyの実装が紹介されているので、その部分だけ取り出して、機能を減らした実装を組んでみると(ある程度、参考にしていますが、細かなところで違うかもしれません。MSDNなども参考にしたので)
using System;
using System.Runtime.Remoting.Proxies;
Source and Project
何度か調べた事があるのに、透過Proxyという言葉を私は、正しく理解していなかったようです。現状の理解では、利用する側、つまりクライアントが、Proxyを利用していると意識せずに利用されるProxyの事を、透過Proxyというのだと思っています。意識しないとは、Proxyを利用する為の決まった手続きをしないという事であって、調べてそれがProxyであるかどうか判定できないという意味ではないです。
Don Box著の「Essential .NET」に透過Proxyの実装が紹介されているので、その部分だけ取り出して、機能を減らした実装を組んでみると(ある程度、参考にしていますが、細かなところで違うかもしれません。MSDNなども参考にしたので)
using System;
using System.Runtime.Remoting.Proxies;
namespace Art55.AopDemo20121211_001
{
public class MyProxyAttribute : ProxyAttribute
{
public override MarshalByRefObject CreateInstance(Type serverType)
{
var instance = base.CreateInstance(serverType);
var proxy = new MyProxy(instance);
return proxy.GetTransparentProxy() as MarshalByRefObject;
}
}
}
using System;
using System.Diagnostics;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Services;
{
public class MyProxyAttribute : ProxyAttribute
{
public override MarshalByRefObject CreateInstance(Type serverType)
{
var instance = base.CreateInstance(serverType);
var proxy = new MyProxy(instance);
return proxy.GetTransparentProxy() as MarshalByRefObject;
}
}
}
using System;
using System.Diagnostics;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Services;
namespace Art55.AopDemo20121211_001
{
public class MyProxy : RealProxy
{
public MyProxy(MarshalByRefObject target)
: base(RemotingServices.GetRealProxy(target).GetProxiedType())
{
_target = target;
}
{
public class MyProxy : RealProxy
{
public MyProxy(MarshalByRefObject target)
: base(RemotingServices.GetRealProxy(target).GetProxiedType())
{
_target = target;
}
private readonly MarshalByRefObject _target;
public override IMessage Invoke(IMessage msg)
{
var callMessage = (IMethodCallMessage)msg;
Debug.Print(callMessage.MethodName);
{
var callMessage = (IMethodCallMessage)msg;
Debug.Print(callMessage.MethodName);
var ctor = callMessage as IConstructionCallMessage;
if (ctor != null)
{
RealProxy realProxy = RemotingServices.GetRealProxy(_target);
realProxy.InitializeServerObject(ctor);
var transparentProxy = (MarshalByRefObject)GetTransparentProxy();
return EnterpriseServicesHelper.CreateConstructionReturnMessage(ctor, transparentProxy);
}
return RemotingServices.ExecuteMessage(_target, callMessage);
}
}
}
MyProxyAttribute クラスは、属性としてMarshalByRefObjectを継承するクラスに指定すると、コンストラクタに割り込む事ができるクラスです。MyProxyAttributeを指定されたクラスのコンストラクタが呼ばれると、インスタンスが作成されたタイミングで透過Proxyが作成されるように実装されています。
MyProxy クラスは、メソッドが呼ばれたタイミングで呼び出しをIMessageで戻りをIMessage でメッセージをやりとりできるようにInvokeメソッドをオーバーライドさせています。動きを確かめたかったので、余計なことはせず通過するだけのシンプルな作りにしてみまいした。
で、透過Proxyとして利用したい「Calculator1 」クラスを用意します。ポイントはMyProxy属性を付けるだけ、
[MyProxy]
public class Calculator1 : ContextBoundObject
{
public double Add(double x, double y)
{
return x + y;
}
if (ctor != null)
{
RealProxy realProxy = RemotingServices.GetRealProxy(_target);
realProxy.InitializeServerObject(ctor);
var transparentProxy = (MarshalByRefObject)GetTransparentProxy();
return EnterpriseServicesHelper.CreateConstructionReturnMessage(ctor, transparentProxy);
}
return RemotingServices.ExecuteMessage(_target, callMessage);
}
}
}
MyProxyAttribute クラスは、属性としてMarshalByRefObjectを継承するクラスに指定すると、コンストラクタに割り込む事ができるクラスです。MyProxyAttributeを指定されたクラスのコンストラクタが呼ばれると、インスタンスが作成されたタイミングで透過Proxyが作成されるように実装されています。
MyProxy クラスは、メソッドが呼ばれたタイミングで呼び出しをIMessageで戻りをIMessage でメッセージをやりとりできるようにInvokeメソッドをオーバーライドさせています。動きを確かめたかったので、余計なことはせず通過するだけのシンプルな作りにしてみまいした。
で、透過Proxyとして利用したい「Calculator1 」クラスを用意します。ポイントはMyProxy属性を付けるだけ、
[MyProxy]
public class Calculator1 : ContextBoundObject
{
public double Add(double x, double y)
{
return x + y;
}
public double Multiply(double x, double y)
{
return x * y;
}
}
これをクライアント側で利用してみます。
とりあえずnewして利用してみます。
class Program
{
static void Main()
{
var calculator = new Calculator1();
Console.WriteLine(calculator.Add(10, 11));
Console.WriteLine(calculator.Multiply(10, 11));
{
return x * y;
}
}
これをクライアント側で利用してみます。
とりあえずnewして利用してみます。
class Program
{
static void Main()
{
var calculator = new Calculator1();
Console.WriteLine(calculator.Add(10, 11));
Console.WriteLine(calculator.Multiply(10, 11));
Console.WriteLine(RemotingServices.IsTransparentProxy(calculator));
}
}
どこからどうみてもCalculator1クラスをnewして、そのインスタンスを利用しているだけに見えますが、calculator は透過Proxyになっています。
実行してみると
21
110
True
RemotingServices.IsTransparentProxy(calculator));がtrueを返しているので透過Proxyとなっていることがわかります。つまり、クライアント側は、それが透過Proxyであることを意識せずに、また、透過Proxyとなるような手続きを一際せずに利用していることがわかります。
といっても今回の動きを見たかっただけのコードでは、あんまり嬉しくないわけですが、もちっと勉強してから何か書いていきたいと思います。
Source and Project
}
}
どこからどうみてもCalculator1クラスをnewして、そのインスタンスを利用しているだけに見えますが、calculator は透過Proxyになっています。
実行してみると
21
110
True
RemotingServices.IsTransparentProxy(calculator));がtrueを返しているので透過Proxyとなっていることがわかります。つまり、クライアント側は、それが透過Proxyであることを意識せずに、また、透過Proxyとなるような手続きを一際せずに利用していることがわかります。
といっても今回の動きを見たかっただけのコードでは、あんまり嬉しくないわけですが、もちっと勉強してから何か書いていきたいと思います。
Source and Project