diff Source/Aspects/Builders/ClearCacheAspectBuilder.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Aspects/Builders/ClearCacheAspectBuilder.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,133 @@
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+
+using BLToolkit.Reflection.Emit;
+using BLToolkit.TypeBuilder.Builders;
+
+namespace BLToolkit.Aspects.Builders
+{
+	public class ClearCacheAspectBuilder : AbstractTypeBuilderBase
+	{
+		#region Init
+
+		public ClearCacheAspectBuilder(Type declaringType, string methodName, Type[] parameterTypes)
+		{
+			_declaringType  = declaringType;
+			_methodName     = methodName;
+			_parameterTypes = parameterTypes;
+		}
+
+		private readonly Type   _declaringType;
+		private readonly string _methodName;
+		private readonly Type[] _parameterTypes;
+
+		#endregion
+
+		#region Overrides
+
+		public override int GetPriority(BuildContext context)
+		{
+			return TypeBuilderConsts.Priority.ClearCacheAspect;
+		}
+
+		public override bool IsCompatible(BuildContext context, IAbstractTypeBuilder typeBuilder)
+		{
+			return true;
+		}
+
+		public override bool IsApplied(BuildContext context, AbstractTypeBuilderList builders)
+		{
+			if (context == null) throw new ArgumentNullException("context");
+
+			return context.IsFinallyStep && context.IsMethodOrProperty;
+		}
+
+		#endregion
+
+		#region Build
+
+		private static int _methodCounter;
+
+		public override void Build(BuildContext context)
+		{
+			Context = context;
+
+			if (string.IsNullOrEmpty(_methodName))
+			{
+				FieldBuilder type = Context.CreatePrivateStaticField(
+					"_type$ClearCacheAspect$" + ++_methodCounter, typeof(Type));
+
+				EmitHelper emit = Context.MethodBuilder.Emitter;
+				Label checkType = emit.DefineLabel();
+
+				emit
+					.ldsfld    (type)
+					.brtrue_s  (checkType)
+					.ldarg_0
+					.LoadType  (_declaringType)
+					.call      (typeof(ClearCacheAspect), "GetType", typeof(object), typeof(Type))
+					.stsfld    (type)
+					.MarkLabel (checkType)
+					.ldsfld    (type)
+					.call      (typeof(CacheAspect), "ClearCache", typeof(Type))
+					;
+			}
+			else
+			{
+				FieldBuilder methodInfo = Context.CreatePrivateStaticField(
+					"_methodInfo$ClearCacheAspect$" + ++_methodCounter, typeof(MethodInfo));
+
+				EmitHelper emit = Context.MethodBuilder.Emitter;
+
+				Label checkMethodInfo = emit.DefineLabel();
+
+				emit
+					.ldsfld   (methodInfo)
+					.brtrue_s (checkMethodInfo)
+					.ldarg_0
+					.LoadType (_declaringType)
+					.ldstrEx  (_methodName)
+					;
+
+				if (_parameterTypes == null || _parameterTypes.Length == 0)
+				{
+					emit.ldnull.end();
+				}
+				else
+				{
+					LocalBuilder field = emit.DeclareLocal(typeof(Type[]));
+
+					emit
+						.ldc_i4_ (_parameterTypes.Length)
+						.newarr  (typeof(Type))
+						.stloc   (field)
+						;
+
+					for (int i = 0; i < _parameterTypes.Length; i++)
+					{
+						emit
+							.ldloc      (field)
+							.ldc_i4     (i)
+							.LoadType   (_parameterTypes[i])
+							.stelem_ref
+							.end()
+							;
+					}
+
+					emit.ldloc(field);
+				}
+
+				emit
+					.call      (typeof(ClearCacheAspect), "GetMethodInfo", typeof(object), typeof(Type), typeof(string), typeof(Type[]))
+					.stsfld    (methodInfo)
+					.MarkLabel (checkMethodInfo)
+					.ldsfld    (methodInfo)
+					.call      (typeof(CacheAspect), "ClearCache", typeof(MethodInfo))
+					;
+			}
+		}
+
+		#endregion
+	}
+}