tutorials.de Buch-Aktion 05/2012
RSS-Feed anzeigen

Thomas Darimont's Blog

[.Net] DynamicProxies

Bewerten
von Thomas Darimont am 07.04.07 um 01:06 (431 Hits)
Hallo,

Norbert hat in seinem Blog ein Beispiel veröffentlich das das Proxy Pattern vorführt.

Neben der gezeigten statischen Version gibt es natürlich auch eine dynamische Ausprägung davon (Dynamic Proxies). Dabei wird die Proxy Implementierung zur Compilezeit nicht fest mit dem zu Interface verdrahtet, das geproxied werden soll, sondern implementiert dieses per IL-Codegenerierung erst zur Laufzeit.

Im .Net Framework selbst gibt es mit der Klasse RealProxy eine Implementierung für DynamicProxies, die eigentlich für Remoting zwecke verwendet wird.

Hier mal ein Beispiel wie man das von Norbert gezeigte ein wenig "dynamisieren" kann
Code csharp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
using System;
using System.Collections.Generic;
using System.Text;
 
using System.Reflection;
 
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;
 
namespace De.Tutorials.Training
{
    public class SimpleDynamicProxyExample
    {
        public static void Main(string[] args)
        {
            //Wir erzeugen unsere richtige Implementierung ...
            ICalculator calcuatorImpl = new Calculator();
 
            //Wir erzeugen unseren InvocationHandler der die Logik enthält die wir "um" unseren eigentlichen Methodenaufruf wrappen wollen
            IInvocationHandler invocationHandler = new LoggingInvocationHandler();
            invocationHandler.Target = calcuatorImpl;
            // anstatt nur einen InvocationHandler zu definieren könnte man natürlich auch eine ganze Kette von InvocationHandlern (InvocationHandlerChain) registrieren, welche dann nacheinander abgearbeitet werden.
 
            //Hier erzeugen wir unseren Proxy. Man kann hier den Proxy auf ICalculator casten, obwohl dieser das ICalculator interface
            //nicht implementiert... das stimmt natürlich nicht ganz. Zur Laufzeit wird IL Code generiert, welcher das interface
            //dynamisch zur laufzeit implementiert (daher der name DYNAMICProxy)
            ICalculator calculatorProxy = (ICalculator)new GenericProxy(typeof(ICalculator), 
                                                                        calcuatorImpl,
                                                                        invocationHandler).GetTransparentProxy();
            Console.WriteLine(calculatorProxy.Add(1, 2)); 
        }
    }
 
    public interface ICalculator
    {
        decimal Add(decimal x, decimal y);
        decimal Sub(decimal x, decimal y);
    }
 
    public class Calculator : ICalculator
    {
        public decimal Add(decimal x, decimal y)
        {
            return x + y;
        }
 
        public decimal Sub(decimal x, decimal y)
        {
            return x - y;
        }
    }
 
    public interface IInvocationHandler
    {
        object Target
        {
            get;
            set;
        }
 
        object Invoke(object proxy, MethodBase methodBase, object[] arguments);
    }
 
    public class LoggingInvocationHandler : IInvocationHandler
    {
        public object Target
        {
            get { return target; }
            set { target = value; }
        } private object target;
 
        public object Invoke(object proxy, MethodBase methodBase, object[] arguments)
        {
            Console.WriteLine("Before: " + methodBase.Name);
            object result = methodBase.Invoke(target, arguments);
            Console.WriteLine("After: " + methodBase.Name);
            return result;
        }
    }
 
    public class GenericProxy : RealProxy
    {
        public IInvocationHandler InvocationHandler
        {
            get { return invocationHandler; }
            set { invocationHandler = value; }
        } private IInvocationHandler invocationHandler;
 
        public GenericProxy(Type type, object target, IInvocationHandler invocationHandler)
            : base(type)
        {
            this.invocationHandler = invocationHandler;
        }
 
        public override IMessage Invoke(IMessage message)
        {
            IMethodCallMessage methodCallMessage = (IMethodCallMessage)message;
            try
            {
                object result = invocationHandler.Invoke(this,
                                                         methodCallMessage.MethodBase,
                                                         methodCallMessage.InArgs);
 
                return new ReturnMessage(result, null, 0, methodCallMessage.LogicalCallContext, methodCallMessage);
            }
            catch (TargetInvocationException targetInvocationException)
            {
                return new ReturnMessage(targetInvocationException, methodCallMessage);
            }
        }
    }
}

Ausgabe:
Code :
1
2
3
Before: Add
After: Add
3

Es gibt natürlich noch einige weitere DynamicProxy implementierungen für .Net ein weiteres Beispiel wäre: DynamicProxy des Castle Projects
...

Über System.Reflection.Emit hat man natürlich auch die Möglichkeit selbst entsprechenden ILCode zur Laufzeit zu generieren und so eine eigene DynamicProxy Lösung zu schaffen die den Anforderungen entspricht.

Gruß Tom

"[.Net] DynamicProxies" bei Twitter speichern "[.Net] DynamicProxies" bei Facebook speichern

Kategorien
Programming

Kommentare