/Xtensive.Core/Xtensive.Core.Weaver/ImplementFactoryMethodWeaver.cs

https://code.google.com/p/dataobjectsdotnet/ · C# · 170 lines · 127 code · 33 blank · 10 comment · 2 complexity · f2af2e24323562cb9590d1d7d249322c MD5 · raw file

  1. // Copyright (C) 2010 Xtensive LLC.
  2. // All rights reserved.
  3. // For conditions of distribution and use, see license.
  4. // Created by: Alexis Kochetov
  5. // Created: 2010.04.07
  6. using System;
  7. using System.Linq;
  8. using System.Reflection;
  9. using PostSharp.AspectInfrastructure;
  10. using PostSharp.AspectWeaver;
  11. using PostSharp.AspectWeaver.AspectWeavers;
  12. using PostSharp.AspectWeaver.Transformations;
  13. using PostSharp.CodeModel;
  14. using PostSharp.CodeModel.Helpers;
  15. using PostSharp.CodeWeaver;
  16. using PostSharp.Extensibility;
  17. using Xtensive.Core.Aspects;
  18. using Xtensive.Core.Reflection;
  19. namespace Xtensive.Core.Weaver
  20. {
  21. internal class ImplementFactoryMethodWeaver : TypeLevelAspectWeaver
  22. {
  23. private ImplementFactoryMethodTransformation transformation;
  24. protected override void Initialize()
  25. {
  26. base.Initialize();
  27. transformation = new ImplementFactoryMethodTransformation(this);
  28. ApplyEffectWaivers(transformation);
  29. RequiresRuntimeInstance = false;
  30. RequiresRuntimeInstanceInitialization = false;
  31. RequiresRuntimeReflectionObject = false;
  32. }
  33. protected override AspectWeaverInstance CreateAspectWeaverInstance(AspectInstanceInfo aspectInstanceInfo)
  34. {
  35. return new Instance(this, aspectInstanceInfo);
  36. }
  37. // Constructors
  38. public ImplementFactoryMethodWeaver()
  39. : base(null, MulticastTargets.Class)
  40. { }
  41. // Nested class
  42. private class Instance : TypeLevelAspectWeaverInstance
  43. {
  44. private readonly ImplementFactoryMethodWeaver parent;
  45. public override void ProvideAspectTransformations(AspectWeaverTransformationAdder adder)
  46. {
  47. adder.Add(TargetElement, parent.transformation.CreateInstance(this));
  48. }
  49. public Instance(ImplementFactoryMethodWeaver parent, AspectInstanceInfo aspectInstanceInfo)
  50. : base(parent, aspectInstanceInfo)
  51. {
  52. this.parent = parent;
  53. }
  54. }
  55. }
  56. internal class ImplementFactoryMethodTransformation : StructuralTransformation
  57. {
  58. public override string GetDisplayName(MethodSemantics semantic)
  59. {
  60. return "Implementing factory method";
  61. }
  62. public AspectWeaverTransformationInstance CreateInstance(AspectWeaverInstance aspectWeaverInstance)
  63. {
  64. var module = AspectWeaver.Module;
  65. var aspect = (ImplementFactoryMethod)aspectWeaverInstance.Aspect;
  66. var argumentTypes = aspect.ParameterTypes.Select(t => module.Cache.GetType(t)).ToArray();
  67. return new Instance(this, aspectWeaverInstance, argumentTypes);
  68. }
  69. // Constructors
  70. public ImplementFactoryMethodTransformation(AspectWeaver aspectWeaver)
  71. : base(aspectWeaver)
  72. {
  73. }
  74. // Nested class
  75. private class Instance : StructuralTransformationInstance
  76. {
  77. private const string ParameterNamePrefix = "arg";
  78. private readonly ITypeSignature[] argumentTypes;
  79. public override void Implement(StructuralTransformationContext context)
  80. {
  81. var typeDef = (TypeDefDeclaration)context.TargetElement;
  82. var genericType = GenericHelper.GetTypeCanonicalGenericInstance(typeDef);
  83. var module = AspectWeaver.Module;
  84. var helper = new WeavingHelper(module);
  85. var ctorSignature = new MethodSignature(
  86. module,
  87. CallingConvention.HasThis,
  88. module.Cache.GetIntrinsic(IntrinsicType.Void),
  89. argumentTypes,
  90. 0);
  91. IMethod constructor;
  92. try {
  93. constructor = genericType.Methods.GetMethod(WellKnown.CtorName,
  94. ctorSignature.Translate(module),
  95. BindingOptions.Default);
  96. } catch (Exception e) {
  97. ErrorLog.Write(SeverityType.Warning, "{0}", e);
  98. return;
  99. }
  100. var factoryMathodDef = new MethodDefDeclaration();
  101. factoryMathodDef.Name = DelegateHelper.AspectedFactoryMethodName;
  102. factoryMathodDef.CallingConvention = CallingConvention.Default;
  103. factoryMathodDef.Attributes = MethodAttributes.Private | MethodAttributes.Static;
  104. typeDef.Methods.Add(factoryMathodDef);
  105. factoryMathodDef.ReturnParameter = new ParameterDeclaration();
  106. factoryMathodDef.ReturnParameter.ParameterType = genericType;
  107. factoryMathodDef.ReturnParameter.Attributes = ParameterAttributes.Retval;
  108. factoryMathodDef.CustomAttributes.Add(helper.GetDebuggerNonUserCodeAttribute());
  109. factoryMathodDef.CustomAttributes.Add(helper.GetCompilerGeneratedAttribute());
  110. for (int i = 0; i < argumentTypes.Length; i++) {
  111. var parameter = new ParameterDeclaration(i, ParameterNamePrefix+i, argumentTypes[i]);
  112. factoryMathodDef.Parameters.Add(parameter);
  113. }
  114. var body = new MethodBodyDeclaration();
  115. factoryMathodDef.MethodBody = body;
  116. var instructionBlock = body.CreateInstructionBlock();
  117. body.RootInstructionBlock = instructionBlock;
  118. var sequence = body.CreateInstructionSequence();
  119. instructionBlock.AddInstructionSequence(sequence, PostSharp.Collections.NodePosition.Before, null);
  120. using (var writer = new InstructionWriter()) {
  121. writer.AttachInstructionSequence(sequence);
  122. for (short i = 0; i < argumentTypes.Length; i++)
  123. writer.EmitInstructionParameter(OpCodeNumber.Ldarg, factoryMathodDef.Parameters[i]);
  124. writer.EmitInstructionMethod(OpCodeNumber.Newobj, constructor);
  125. writer.EmitInstruction(OpCodeNumber.Ret);
  126. writer.DetachInstructionSequence();
  127. }
  128. }
  129. // Constructors
  130. public Instance(ImplementFactoryMethodTransformation parent, AspectWeaverInstance aspectWeaverInstance, ITypeSignature[] argumentTypes)
  131. : base(parent, aspectWeaverInstance)
  132. {
  133. this.argumentTypes = argumentTypes;
  134. }
  135. }
  136. }
  137. }