private void BuildLazyInstanceEnsurer() { string fieldName = GetFieldName(); FieldBuilder field = Context.GetField(fieldName); TypeHelper fieldType = new TypeHelper(field.FieldType); TypeHelper objectType = new TypeHelper(GetObjectType()); MethodBuilderHelper ensurer = Context.TypeBuilder.DefineMethod( string.Format("$EnsureInstance{0}", fieldName), MethodAttributes.Private | MethodAttributes.HideBySig); EmitHelper emit = ensurer.Emitter; Label end = emit.DefineLabel(); emit .ldarg_0 .ldfld (field) .brtrue_s (end) ; object[] parameters = TypeHelper.GetPropertyParameters(Context.CurrentProperty); ConstructorInfo ci = objectType.GetPublicConstructor(typeof(InitContext)); if (ci != null || objectType.IsAbstract) CreateInitContextLazyInstance(field, fieldType, objectType, emit, parameters); else if (parameters == null) CreateDefaultInstance(field, fieldType, objectType, emit); else CreateParametrizedInstance(field, fieldType, objectType, emit, parameters); emit .MarkLabel(end) .ret() ; Context.Items.Add("$BLToolkit.FieldInstanceEnsurer." + fieldName, ensurer); }
private void CreateInitContextLazyInstance( FieldBuilder field, TypeHelper fieldType, TypeHelper objectType, EmitHelper emit, object[] parameters) { if (!CheckObjectHolderCtor(fieldType, objectType)) return; LocalBuilder initField = emit.DeclareLocal(InitContextType); emit .newobj (InitContextType.GetPublicDefaultConstructor()) .dup .ldarg_0 .callvirt (InitContextType.GetProperty("Parent").GetSetMethod()) .dup .ldc_i4_1 .callvirt (InitContextType.GetProperty("IsInternal").GetSetMethod()) .dup .ldc_i4_1 .callvirt (InitContextType.GetProperty("IsLazyInstance").GetSetMethod()) ; if (parameters != null) { emit .dup .ldsfld (GetParameterField()) .callvirt (InitContextType.GetProperty("MemberParameters").GetSetMethod()) ; } emit .stloc (initField); if (objectType.IsAbstract) { emit .ldarg_0 .ldsfld (GetTypeAccessorField()) .ldloc (initField) .callvirtNoGenerics (typeof(TypeAccessor), "CreateInstanceEx", _initContextType) .isinst (objectType) ; } else { emit .ldarg_0 .ldloc (initField) .newobj (objectType.GetPublicConstructor(typeof(InitContext))) ; } if (IsObjectHolder) { emit .newobj (fieldType, objectType) ; } emit .stfld (field) ; }
private bool CheckObjectHolderCtor(TypeHelper fieldType, TypeHelper objectType) { if (IsObjectHolder) { ConstructorInfo holderCi = fieldType.GetPublicConstructor(objectType); if (holderCi == null) { string message = string.Format( Resources.TypeBuilder_PropertyTypeHasNoCtorWithParamType, Context.CurrentProperty.Name, Context.Type.FullName, fieldType.FullName, objectType.FullName); Context.TypeBuilder.DefaultConstructor.Emitter .ldstr (message) .newobj (typeof(TypeBuilderException), typeof(string)) .@throw .end() ; return false; } } return true; }
private void CreateInitContextDefaultInstance( string initContextName, FieldBuilder field, TypeHelper fieldType, TypeHelper objectType, EmitHelper emit, object[] parameters) { if (!CheckObjectHolderCtor(fieldType, objectType)) return; LocalBuilder initField = GetInitContextBuilder(initContextName, emit); MethodInfo memberParams = InitContextType.GetProperty("MemberParameters").GetSetMethod(); if (parameters != null) { emit .ldloc (initField) .ldsfld (GetParameterField()) .callvirt (memberParams) ; } else if ((bool)Context.Items["$BLToolkit.Default.DirtyParameters"]) { emit .ldloc (initField) .ldnull .callvirt (memberParams) ; } Context.Items["$BLToolkit.Default.DirtyParameters"] = parameters != null; if (objectType.IsAbstract) { emit .ldarg_0 .ldsfld (GetTypeAccessorField()) .ldloc (initField) .callvirtNoGenerics (typeof(TypeAccessor), "CreateInstanceEx", _initContextType) .isinst (objectType) ; } else { emit .ldarg_0 .ldloc (initField) .newobj (objectType.GetPublicConstructor(typeof(InitContext))) ; } if (IsObjectHolder) { emit .newobj (fieldType, objectType) ; } emit .stfld (field) ; }
private void BuildDefaultInstance() { string fieldName = GetFieldName(); FieldBuilder field = Context.GetField(fieldName); TypeHelper fieldType = new TypeHelper(field.FieldType); TypeHelper objectType = new TypeHelper(GetObjectType()); EmitHelper emit = Context.TypeBuilder.DefaultConstructor.Emitter; object[] ps = TypeHelper.GetPropertyParameters(Context.CurrentProperty); ConstructorInfo ci = objectType.GetPublicConstructor(typeof(InitContext)); if (ci != null && ci.GetParameters()[0].ParameterType != typeof(InitContext)) ci = null; if (ci != null || objectType.IsAbstract) CreateInitContextDefaultInstance( "$BLToolkit.DefaultInitContext.", field, fieldType, objectType, emit, ps); else if (ps == null) CreateDefaultInstance(field, fieldType, objectType, emit); else CreateParametrizedInstance(field, fieldType, objectType, emit, ps); }
private void CreateAbstractInitContextInstance( FieldBuilder field, TypeHelper fieldType, TypeHelper objectType, EmitHelper emit, object[] parameters) { if (!CheckObjectHolderCtor(fieldType, objectType)) return; MethodInfo memberParams = InitContextType.GetProperty("MemberParameters").GetSetMethod(); LocalBuilder parentField = (LocalBuilder)Context.Items["$BLToolkit.InitContext.Parent"]; if (parentField == null) { Context.Items["$BLToolkit.InitContext.Parent"] = parentField = emit.DeclareLocal(typeof(object)); Label label = emit.DefineLabel(); emit .ldarg_1 .brtrue_s (label) .newobj (InitContextType.GetPublicDefaultConstructor()) .starg (1) .ldarg_1 .ldc_i4_1 .callvirt (InitContextType.GetProperty("IsInternal").GetSetMethod()) .MarkLabel (label) .ldarg_1 .callvirt (InitContextType.GetProperty("Parent").GetGetMethod()) .stloc (parentField) ; } emit .ldarg_1 .ldarg_0 .callvirt (InitContextType.GetProperty("Parent").GetSetMethod()) ; object isDirty = Context.Items["$BLToolkit.InitContext.DirtyParameters"]; if (parameters != null) { emit .ldarg_1 .ldsfld (GetParameterField()) .callvirt (memberParams) ; } else if (isDirty != null && (bool)isDirty) { emit .ldarg_1 .ldnull .callvirt (memberParams) ; } Context.Items["$BLToolkit.InitContext.DirtyParameters"] = parameters != null; if (objectType.IsAbstract) { emit .ldarg_0 .ldsfld (GetTypeAccessorField()) .ldarg_1 .callvirtNoGenerics (typeof(TypeAccessor), "CreateInstanceEx", _initContextType) .isinst (objectType) ; } else { emit .ldarg_0 .ldarg_1 .newobj (objectType.GetPublicConstructor(typeof(InitContext))) ; } if (IsObjectHolder) { emit .newobj (fieldType, objectType) ; } emit .stfld (field) ; }
private void CreateParametrizedInstance( FieldBuilder field, TypeHelper fieldType, TypeHelper objectType, EmitHelper emit, object[] parameters) { if (!CheckObjectHolderCtor(fieldType, objectType)) return; if (parameters.Length == 1) { object o = parameters[0]; if (o == null) { if (objectType.IsValueType == false) emit .ldarg_0 .ldnull .end() ; if (IsObjectHolder) { emit .newobj (fieldType, objectType) ; } emit .stfld (field) ; return; } else { if (objectType.Type == o.GetType()) { if (objectType.Type == typeof(string)) { emit .ldarg_0 .ldstr ((string)o) .stfld (field) ; return; } if (objectType.IsValueType) { emit.ldarg_0.end(); if (emit.LoadWellKnownValue(o) == false) { emit .ldsfld (GetParameterField()) .ldc_i4_0 .ldelem_ref .end() ; } emit.stfld(field); return; } } } } Type[] types = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { if (parameters[i] != null) { Type t = parameters[i].GetType(); types[i] = (t.IsEnum) ? Enum.GetUnderlyingType(t) : t; } else types[i] = typeof(object); } ConstructorInfo ci = objectType.GetPublicConstructor(types); if (ci == null) { if (objectType.IsValueType) return; throw new TypeBuilderException( string.Format(types.Length == 0? Resources.TypeBuilder_PropertyTypeHasNoPublicDefaultCtor: Resources.TypeBuilder_PropertyTypeHasNoPublicCtor, Context.CurrentProperty.Name, Context.Type.FullName, objectType.FullName)); } ParameterInfo[] pi = ci.GetParameters(); emit.ldarg_0.end(); for (int i = 0; i < parameters.Length; i++) { object o = parameters[i]; Type oType = o.GetType(); if (emit.LoadWellKnownValue(o)) { if (oType.IsValueType) { if (!pi[i].ParameterType.IsValueType) emit.box(oType); else if (Type.GetTypeCode(oType) != Type.GetTypeCode(pi[i].ParameterType)) emit.conv(pi[i].ParameterType); } } else { emit .ldsfld (GetParameterField()) .ldc_i4 (i) .ldelem_ref .CastFromObject (types[i]) ; if (oType.IsValueType && !pi[i].ParameterType.IsValueType) emit.box(oType); } } emit .newobj (ci) ; if (IsObjectHolder) { emit .newobj (fieldType, objectType) ; } emit .stfld (field) ; }
private void BuildInitContextInstance() { var fieldName = GetFieldName(); var field = Context.GetField(fieldName); var fieldType = new TypeHelper(field.FieldType); var objectType = new TypeHelper(GetObjectType()); var emit = Context.TypeBuilder.InitConstructor.Emitter; var parameters = TypeHelper.GetPropertyParameters(Context.CurrentProperty); var ci = objectType.GetPublicConstructor(typeof(InitContext)); if (ci != null && ci.GetParameters()[0].ParameterType != typeof(InitContext)) ci = null; if (ci != null || objectType.IsAbstract) CreateAbstractInitContextInstance(field, fieldType, objectType, emit, parameters); else if (parameters == null) CreateDefaultInstance(field, fieldType, objectType, emit); else CreateParametrizedInstance(field, fieldType, objectType, emit, parameters); }
private Stack<ConstructorInfo> GetGenericNestedConstructors(TypeHelper objectType, Predicate<TypeHelper> isActionable, Action<TypeHelper> action, Func<bool> isBreakCondition) { Stack<ConstructorInfo> genericNestedConstructors = null; if (isActionable(objectType)) action(objectType); while (objectType.Type.IsGenericType && !isBreakCondition()) { var typeArgs = objectType.Type.GetGenericArguments(); if (typeArgs.Length == 1) { var genericCtor = objectType.GetPublicConstructor(typeArgs[0]); if (genericCtor != null) { if (genericNestedConstructors == null) genericNestedConstructors = new Stack<ConstructorInfo>(); genericNestedConstructors.Push(genericCtor); objectType = typeArgs[0]; if (isActionable(objectType)) action(objectType); } } else { throw new TypeBuilderException( string.Format(Resources.TypeBuilder_GenericShouldBeSingleTyped, Context.CurrentProperty.Name, Context.Type.FullName, objectType.FullName)); } } return genericNestedConstructors; }