/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

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