2013-08-21 12 views
6

を使用する理由dynamic proxyクラスは、クラスのインスタンスで インターフェイスのいずれかを介してメソッド呼び出しが符号化さに を派遣されるように、実行時に指定されたインタフェース のリストを実装するクラスであります均一なインタフェースを介して別のオブジェクト。 は、 のプロキシクラスの事前生成を必要とせずに、インターフェイスのリストに対してタイプセーフなプロキシオブジェクトを作成するために使用できます。 タイプセーフな 反射ディスパッチを提供する必要があるアプリケーションまたはライブラリに役立ちます。 enter image description here我々は動的プロキシ

絵の上に存在インターフェース のAPIオブジェクトの呼び出しの我々は、動的プロキシを使用するのはなぜ良いサンプルですけど?

もっと知覚するために、現実世界で使用する簡単な例がありますか?

+1

IMOこの質問が広すぎます、この問題を分離した問題で分割する必要があります – onof

+0

@onof Okありがとう –

答えて

0

このlinkは、コード内で動的プロキシについて説明します。

public static class DynamicProxyGenerator 
{ 
    public static T GetInstanceFor<T>() 
    { 
     Type typeOfT = typeof(T); 
     var methodInfos = typeOfT.GetMethods(); 
     AssemblyName assName = new AssemblyName("testAssembly"); 
     var assBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assName, AssemblyBuilderAccess.RunAndSave); 
     var moduleBuilder = assBuilder.DefineDynamicModule("testModule", "test.dll"); 
     var typeBuilder = moduleBuilder.DefineType(typeOfT.Name + "Proxy", TypeAttributes.Public); 

     typeBuilder.AddInterfaceImplementation(typeOfT); 
     var ctorBuilder = typeBuilder.DefineConstructor( 
        MethodAttributes.Public, 
        CallingConventions.Standard, 
        new Type[] { }); 
     var ilGenerator = ctorBuilder.GetILGenerator(); 
     ilGenerator.EmitWriteLine("Creating Proxy instance"); 
     ilGenerator.Emit(OpCodes.Ret); 
     foreach (var methodInfo in methodInfos) 
     { 
      var methodBuilder = typeBuilder.DefineMethod( 
       methodInfo.Name, 
       MethodAttributes.Public | MethodAttributes.Virtual, 
       methodInfo.ReturnType, 
       methodInfo.GetParameters().Select(p => p.GetType()).ToArray() 
       ); 
      var methodILGen = methodBuilder.GetILGenerator();    
      if (methodInfo.ReturnType == typeof(void)) 
      { 
       methodILGen.Emit(OpCodes.Ret); 
      } 
      else 
      { 
       if (methodInfo.ReturnType.IsValueType || methodInfo.ReturnType.IsEnum) 
       { 
        MethodInfo getMethod = typeof(Activator).GetMethod(/span>"CreateInstance",new Type[]{typeof((Type)});       
        LocalBuilder lb = methodILGen.DeclareLocal(methodInfo.ReturnType); 
        methodILGen.Emit(OpCodes.Ldtoken, lb.LocalType); 
        methodILGen.Emit(OpCodes.Call, typeofype).GetMethod("GetTypeFromHandle")); )); 
        methodILGen.Emit(OpCodes.Callvirt, getMethod); 
        methodILGen.Emit(OpCodes.Unbox_Any, lb.LocalType); 

       } 
       else 
       { 
        methodILGen.Emit(OpCodes.Ldnull); 
       } 
       methodILGen.Emit(OpCodes.Ret); 
      } 
      typeBuilder.DefineMethodOverride(methodBuilder, methodInfo); 
     } 

     Type constructedType = typeBuilder.CreateType(); 
     var instance = Activator.CreateInstance(constructedType); 
     return (T)instance; 
    } 
} 
+0

これは特定のC#実装ですが、可能なアプリケーションについては説明しません。 fパターン – STW

+0

私が既に言ったように、このリンクは動的プロキシをコードで記述します。私はそれが質問に対する良い実用的な答えになると思ったので、それは自分自身にはとても分かりました。 –

3

一般的なケースはAspect-Oriented Programmingです。コンポーネント自体に機能を実装することなく、多くのコンポーネントにわたって共通の機能を適用しようとしています。このような場合、ダイナミックプロキシを使用して、すべてのターゲティングコンポーネントを追加の動作でラップすることができます。そう

カップルの例をやって:そのようHibernateとEntity Frameworkのよう

  • のORMは、コード最初のデザインを中心に持続性の実装を提供するために、これを行います。コアドメインクラスは永続性を知らずに構築され、フレームワークは起動時にこれらのクラスをラップまたは拡張して実際の実装を処理します。

  • インターフェイスのすべてのメンバーをロギングやキャッシングなどのアスペクトでラップします。たとえば、すべてのメソッド呼び出しをISomeInterfaceに記録する場合は、すべてのインターフェイスメソッドを検出する動的プロキシを記述し、メソッドの詳細を使用してLogメソッドを呼び出してから、呼び出しを実際の実装に渡します。

2

CanDriveとCanFloatのインターフェイスを実装するCarとMotorboatの2つのオブジェクトがあるとします。ここでは、これらのインターフェースを実装し、CarとMotorboatのロジックを再利用する3つ目のオブジェクトを作成したいとします。 Groovy、Ruby、Scalaのような言語では、mixinを使って解決することができます。しかし、Javaでは、そのようなことはありません。もちろん、たとえばアダプタ設計パターンですが、多くの場合(特にフレームワークを構築する場合)、動的プロキシが有用になります。 CGLIBライブラリを使用する例を考えてみましょう。

CanDrive car = new Car(); 
CanFloat motorboat = new Motorboat(); 

net.sf.cglib.proxy.Mixin amphibian = net.sf.cglib.proxy.Mixin.create(new Object[] { car, motorboat }); 

TestCase.assertEquals("bzzz bzzz bzzz ...", ((CanFloat) amphibian)._float()); 
TestCase.assertEquals("pyr pyr pyr pyr ...", ((CanDrive) amphibian).drive());