Mercurial > pub > bltoolkit
view Source/TypeBuilder/Builders/AbstractTypeBuilderBase.cs @ 4:f757da6161a1
!bug 100 + 2h fixed gregression
author | cin |
---|---|
date | Sun, 24 Aug 2014 17:57:42 +0400 |
parents | f990fcb411a9 |
children |
line wrap: on
line source
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 } }