diff Source/TypeBuilder/Builders/AbstractTypeBuilderBase.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/TypeBuilder/Builders/AbstractTypeBuilderBase.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,428 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics;
+
+using BLToolkit.Reflection;
+using BLToolkit.Reflection.Emit;
+
+namespace BLToolkit.TypeBuilder.Builders
+{
+	public abstract class AbstractTypeBuilderBase : IAbstractTypeBuilder
+	{
+		public virtual Type[] GetInterfaces()
+		{
+			return null;
+		}
+
+		private int _id;
+		public  int  ID
+		{
+			get { return _id;  }
+			set { _id = value; }
+		}
+
+		private object _targetElement;
+		public  object  TargetElement
+		{
+			get { return _targetElement;  }
+			set { _targetElement = value; }
+		}
+
+		private BuildContext _context;
+		public  BuildContext  Context
+		{
+			[DebuggerStepThrough] get { return _context;  }
+			[DebuggerStepThrough] set { _context = value; }
+		}
+
+		public virtual bool IsCompatible(BuildContext context, IAbstractTypeBuilder typeBuilder)
+		{
+			return true;
+		}
+
+		protected bool IsRelative(IAbstractTypeBuilder typeBuilder)
+		{
+			if (typeBuilder == null) throw new ArgumentNullException("typeBuilder");
+
+			return GetType().IsInstanceOfType(typeBuilder) || typeBuilder.GetType().IsInstanceOfType(this);
+		}
+
+		public virtual bool IsApplied(BuildContext context, AbstractTypeBuilderList builders)
+		{
+			return false;
+		}
+
+		public virtual int GetPriority(BuildContext context)
+		{
+			return TypeBuilderConsts.Priority.Normal;
+		}
+
+		public virtual void Build(BuildContext context)
+		{
+			if (context == null) throw new ArgumentNullException("context");
+
+			Context = context;
+
+			switch (context.Step)
+			{
+				case BuildStep.Begin: BeginMethodBuild(); return;
+				case BuildStep.End:   EndMethodBuild();   return;
+			}
+
+			switch (context.BuildElement)
+			{
+				case BuildElement.Type:
+					switch (context.Step)
+					{
+						case BuildStep.Before:   BeforeBuildType(); break;
+						case BuildStep.Build:          BuildType(); break;
+						case BuildStep.After:     AfterBuildType(); break;
+						case BuildStep.Catch:     CatchBuildType(); break;
+						case BuildStep.Finally: FinallyBuildType(); break;
+					}
+
+					break;
+
+				case BuildElement.AbstractGetter:
+					switch (context.Step)
+					{
+						case BuildStep.Before:   BeforeBuildAbstractGetter(); break;
+						case BuildStep.Build:          BuildAbstractGetter(); break;
+						case BuildStep.After:     AfterBuildAbstractGetter(); break;
+						case BuildStep.Catch:     CatchBuildAbstractGetter(); break;
+						case BuildStep.Finally: FinallyBuildAbstractGetter(); break;
+					}
+
+					break;
+
+				case BuildElement.AbstractSetter:
+					switch (context.Step)
+					{
+						case BuildStep.Before:   BeforeBuildAbstractSetter(); break;
+						case BuildStep.Build:          BuildAbstractSetter(); break;
+						case BuildStep.After:     AfterBuildAbstractSetter(); break;
+						case BuildStep.Catch:     CatchBuildAbstractSetter(); break;
+						case BuildStep.Finally: FinallyBuildAbstractSetter(); break;
+					}
+
+					break;
+
+				case BuildElement.AbstractMethod:
+					switch (context.Step)
+					{
+						case BuildStep.Before:   BeforeBuildAbstractMethod(); break;
+						case BuildStep.Build:          BuildAbstractMethod(); break;
+						case BuildStep.After:     AfterBuildAbstractMethod(); break;
+						case BuildStep.Catch:     CatchBuildAbstractMethod(); break;
+						case BuildStep.Finally: FinallyBuildAbstractMethod(); break;
+					}
+
+					break;
+
+				case BuildElement.VirtualGetter:
+					switch (context.Step)
+					{
+						case BuildStep.Before:   BeforeBuildVirtualGetter(); break;
+						case BuildStep.Build:          BuildVirtualGetter(); break;
+						case BuildStep.After:     AfterBuildVirtualGetter(); break;
+						case BuildStep.Catch:     CatchBuildVirtualGetter(); break;
+						case BuildStep.Finally: FinallyBuildVirtualGetter(); break;
+					}
+
+					break;
+
+				case BuildElement.VirtualSetter:
+					switch (context.Step)
+					{
+						case BuildStep.Before:   BeforeBuildVirtualSetter(); break;
+						case BuildStep.Build:          BuildVirtualSetter(); break;
+						case BuildStep.After:     AfterBuildVirtualSetter(); break;
+						case BuildStep.Catch:     CatchBuildVirtualSetter(); break;
+						case BuildStep.Finally: FinallyBuildVirtualSetter(); break;
+					}
+
+					break;
+
+				case BuildElement.VirtualMethod:
+					switch (context.Step)
+					{
+						case BuildStep.Before:   BeforeBuildVirtualMethod(); break;
+						case BuildStep.Build:          BuildVirtualMethod(); break;
+						case BuildStep.After:     AfterBuildVirtualMethod(); break;
+						case BuildStep.Catch:     CatchBuildVirtualMethod(); break;
+						case BuildStep.Finally: FinallyBuildVirtualMethod(); break;
+					}
+
+					break;
+
+				case BuildElement.InterfaceMethod:
+					BuildInterfaceMethod();
+					break;
+			}
+		}
+
+		protected virtual void  BeforeBuildType          () {}
+		protected virtual void        BuildType          () {}
+		protected virtual void   AfterBuildType          () {}
+		protected virtual void   CatchBuildType          () {}
+		protected virtual void FinallyBuildType          () {}
+
+		protected virtual void  BeforeBuildAbstractGetter() {}
+		protected virtual void        BuildAbstractGetter() {}
+		protected virtual void   AfterBuildAbstractGetter() {}
+		protected virtual void   CatchBuildAbstractGetter() {}
+		protected virtual void FinallyBuildAbstractGetter() {}
+
+		protected virtual void  BeforeBuildAbstractSetter() {}
+		protected virtual void        BuildAbstractSetter() {}
+		protected virtual void   AfterBuildAbstractSetter() {}
+		protected virtual void   CatchBuildAbstractSetter() {}
+		protected virtual void FinallyBuildAbstractSetter() {}
+
+		protected virtual void  BeforeBuildAbstractMethod() {}
+		protected virtual void        BuildAbstractMethod() {}
+		protected virtual void   AfterBuildAbstractMethod() {}
+		protected virtual void   CatchBuildAbstractMethod() {}
+		protected virtual void FinallyBuildAbstractMethod() {}
+
+		protected virtual void  BeforeBuildVirtualGetter () {}
+		protected virtual void        BuildVirtualGetter () {}
+		protected virtual void   AfterBuildVirtualGetter () {}
+		protected virtual void   CatchBuildVirtualGetter () {}
+		protected virtual void FinallyBuildVirtualGetter () {}
+
+		protected virtual void  BeforeBuildVirtualSetter () {}
+		protected virtual void        BuildVirtualSetter () {}
+		protected virtual void   AfterBuildVirtualSetter () {}
+		protected virtual void   CatchBuildVirtualSetter () {}
+		protected virtual void FinallyBuildVirtualSetter () {}
+
+		protected virtual void  BeforeBuildVirtualMethod () {}
+		protected virtual void        BuildVirtualMethod () {}
+		protected virtual void   AfterBuildVirtualMethod () {}
+		protected virtual void   CatchBuildVirtualMethod () {}
+		protected virtual void FinallyBuildVirtualMethod () {}
+
+		protected virtual void BuildInterfaceMethod      () {}
+
+		protected virtual void BeginMethodBuild          () {}
+		protected virtual void   EndMethodBuild          () {}
+
+		#region Helpers
+
+		[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
+		protected bool CallLazyInstanceInsurer(FieldBuilder field)
+		{
+			if (field == null) throw new ArgumentNullException("field");
+
+			MethodBuilderHelper ensurer = Context.GetFieldInstanceEnsurer(field.Name);
+
+			if (ensurer != null)
+			{
+				Context.MethodBuilder.Emitter
+					.ldarg_0
+					.call    (ensurer);
+			}
+
+			return ensurer != null;
+		}
+
+		[SuppressMessage("Microsoft.Performance", "CA1818:DoNotConcatenateStringsInsideLoops")]
+		protected virtual string GetFieldName(PropertyInfo propertyInfo)
+		{
+			string name = propertyInfo.Name;
+
+			if (char.IsUpper(name[0]) && name.Length > 1 && char.IsLower(name[1]))
+				name = char.ToLower(name[0]) + name.Substring(1, name.Length - 1);
+
+			name = "_" + name;
+
+			foreach (ParameterInfo p in propertyInfo.GetIndexParameters())
+				name += "." + p.ParameterType.FullName;//.Replace(".", "_").Replace("+", "_");
+
+			return name;
+		}
+
+		protected string GetFieldName()
+		{
+			return GetFieldName(Context.CurrentProperty);
+		}
+
+		protected FieldBuilder GetPropertyInfoField(PropertyInfo property)
+		{
+			string       fieldName = GetFieldName(property) + "_$propertyInfo";
+			FieldBuilder field     = Context.GetField(fieldName);
+
+			if (field == null)
+			{
+				field = Context.CreatePrivateStaticField(fieldName, typeof(PropertyInfo));
+
+				EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter;
+
+				ParameterInfo[] index      = property.GetIndexParameters();
+
+				emit
+					.LoadType (Context.Type)
+					.ldstr    (property.Name)
+					.LoadType (property.PropertyType)
+					;
+
+				if (index.Length == 0)
+				{
+					emit
+						.ldsfld (typeof(Type).GetField("EmptyTypes"))
+						;
+				}
+				else
+				{
+					emit
+						.ldc_i4 (index.Length) 
+						.newarr (typeof(Type))
+						;
+
+					for (int i = 0; i < index.Length; i++)
+						emit
+							.dup
+							.ldc_i4     (i) 
+							.LoadType   (index[i].ParameterType)
+							.stelem_ref
+							.end()
+							;
+				}
+
+				emit
+					.call   (typeof(TypeHelper).GetMethod("GetPropertyInfo"))
+					.stsfld (field)
+					;
+			}
+
+			return field;
+		}
+
+		protected FieldBuilder GetPropertyInfoField()
+		{
+			return GetPropertyInfoField(Context.CurrentProperty);
+		}
+
+		protected FieldBuilder GetParameterField()
+		{
+			string       fieldName = GetFieldName() + "_$parameters";
+			FieldBuilder field     = Context.GetField(fieldName);
+
+			if (field == null)
+			{
+				field = Context.CreatePrivateStaticField(fieldName, typeof(object[]));
+
+				FieldBuilder piField = GetPropertyInfoField();
+				EmitHelper   emit    = Context.TypeBuilder.TypeInitializer.Emitter;
+
+				emit
+					.ldsfld (piField)
+					.call   (typeof(TypeHelper).GetMethod("GetPropertyParameters"))
+					.stsfld (field)
+					;
+			}
+
+			return field;
+		}
+
+		protected FieldBuilder GetTypeAccessorField()
+		{
+			string       fieldName = "_" + GetObjectType().FullName + "_$typeAccessor";
+			FieldBuilder field     = Context.GetField(fieldName);
+
+			if (field == null)
+			{
+				field = Context.CreatePrivateStaticField(fieldName, typeof(TypeAccessor));
+
+				EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter;
+
+				emit
+					.LoadType (GetObjectType())
+					.call     (typeof(TypeAccessor), "GetAccessor", typeof(Type))
+					.stsfld   (field)
+					;
+			}
+
+			return field;
+		}
+
+		protected FieldBuilder GetArrayInitializer(Type arrayType)
+		{
+			string       fieldName = "_array_of_$_" + arrayType.FullName;
+			FieldBuilder field     = Context.GetField(fieldName);
+
+			if (field == null)
+			{
+				field = Context.CreatePrivateStaticField(fieldName, arrayType);
+
+				EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter;
+
+				int rank = arrayType.GetArrayRank();
+
+				if (rank > 1)
+				{
+					Type[] parameters = new Type[rank];
+
+					for (int i = 0; i < parameters.Length; i++)
+					{
+						parameters[i] = typeof(int);
+						emit.ldc_i4_0.end();
+					}
+
+					ConstructorInfo ci = TypeHelper.GetConstructor(arrayType, parameters);
+
+					emit
+						.newobj (ci)
+						.stsfld (field)
+						;
+				}
+				else
+				{
+					emit
+						.ldc_i4_0
+						.newarr   (arrayType.GetElementType())
+						.stsfld   (field)
+						;
+				}
+			}
+
+			return field;
+		}
+
+		protected FieldBuilder GetArrayInitializer()
+		{
+			return GetArrayInitializer(Context.CurrentProperty.PropertyType);
+		}
+
+		protected virtual Type GetFieldType()
+		{
+			var pi    = Context.CurrentProperty;
+			var index = pi.GetIndexParameters();
+
+			switch (index.Length)
+			{
+				case 0: return pi.PropertyType;
+				case 1: return typeof(Dictionary<object,object>);
+				default:
+					throw new InvalidOperationException();
+			}
+		}
+
+		protected virtual Type GetObjectType()
+		{
+			return GetFieldType();
+		}
+
+		protected virtual bool IsObjectHolder
+		{
+			get { return false; }
+		}
+
+		#endregion
+	}
+}