PageRenderTime 143ms CodeModel.GetById 71ms app.highlight 3ms RepoModel.GetById 67ms app.codeStats 0ms

/src/LinFu.Proxy/ProxyBuilder.cs

http://github.com/philiplaureano/LinFu
C# | 95 lines | 43 code | 12 blank | 40 comment | 6 complexity | 85a0234f09d67091b89247d5a173b56c MD5 | raw file
 1using System;
 2using System.Collections.Generic;
 3using System.Reflection;
 4using LinFu.AOP.Interfaces;
 5using LinFu.IoC.Configuration;
 6using LinFu.IoC.Interfaces;
 7using LinFu.Proxy.Interfaces;
 8using LinFu.Reflection.Emit.Interfaces;
 9using Mono.Cecil;
10
11namespace LinFu.Proxy
12{
13    /// <summary>
14    ///     A <see cref="IProxyBuilder" /> type that generates
15    ///     proxies that forward all virtual method calls to a
16    ///     single interceptor.
17    /// </summary>
18    public class ProxyBuilder : IProxyBuilder, IInitialize
19    {
20        /// <summary>
21        ///     Initializes the current class with the default values.
22        /// </summary>
23        public ProxyBuilder()
24        {
25            ProxyImplementor = new ProxyImplementor();
26            MethodPicker = new MethodPicker();
27            ProxyMethodBuilder = new ProxyMethodBuilder();
28        }
29
30        /// <summary>
31        ///     Gets or sets the <see cref="ITypeBuilder" /> interface
32        ///     which will emit the actual implementation of the IProxy interface.
33        /// </summary>
34        public ITypeBuilder ProxyImplementor { get; set; }
35
36        /// <summary>
37        ///     Gets or sets the <see cref="IMethodPicker" />
38        ///     instance that will determine which methods
39        ///     will be proxied by the proxy builder.
40        /// </summary>
41        public IMethodPicker MethodPicker { get; set; }
42
43        /// <summary>
44        ///     The <see cref="IMethodBuilder" /> instance
45        ///     that will be responsible for generating each method
46        ///     for the current target type.
47        /// </summary>
48        public IMethodBuilder ProxyMethodBuilder { get; set; }
49
50
51        /// <summary>
52        ///     Initializes the current instance
53        ///     with the <paramref name="source" /> container.
54        /// </summary>
55        /// <param name="source">The <see cref="IServiceContainer" /> instance that will hold the current instance.</param>
56        public void Initialize(IServiceContainer source)
57        {
58            ProxyImplementor = (ITypeBuilder) source.GetService("ProxyImplementor", typeof(ITypeBuilder));
59            MethodPicker = (IMethodPicker) source.GetService(typeof(IMethodPicker));
60            ProxyMethodBuilder = (IMethodBuilder) source.GetService("ProxyMethodBuilder", typeof(IMethodBuilder));
61        }
62
63
64        /// <summary>
65        ///     Generates a proxy that forwards all virtual method calls
66        ///     to a single <see cref="IInterceptor" /> instance.
67        /// </summary>
68        /// <param name="originalBaseType">The base class of the type being constructed.</param>
69        /// <param name="baseInterfaces">The list of interfaces that the new type must implement.</param>
70        /// <param name="module">The module that will hold the brand new type.</param>
71        /// <param name="targetType">The <see cref="TypeDefinition" /> that represents the type to be created.</param>
72        public virtual void Construct(Type originalBaseType, IEnumerable<Type> baseInterfaces,
73            ModuleDefinition module, TypeDefinition targetType)
74        {
75            // Determine which interfaces need to be implemented
76            var interfaces = new HashSet<Type>(baseInterfaces);
77
78            // Implement the IProxy interface
79            if (ProxyImplementor != null)
80                ProxyImplementor.Construct(module, targetType);
81
82            // Determine which methods should be proxied
83            IEnumerable<MethodInfo> targetMethods = new MethodInfo[0];
84            if (MethodPicker != null)
85                targetMethods = MethodPicker.ChooseProxyMethodsFrom(originalBaseType, interfaces);
86
87            if (ProxyMethodBuilder == null)
88                return;
89
90            // Generate a proxy method for each
91            // target method
92            foreach (var method in targetMethods) ProxyMethodBuilder.CreateMethod(targetType, method);
93        }
94    }
95}