private static void ImplementGetInspector(PropertyBuilderContext context, Action <PropertyBuilderContext> implement, MethodInfo getInspector) { // Run real implementor first implement(context); // Getter now has value to be returned as single element on stack if (context.GetMethodGenerator != null) { // Store return value in local var LocalBuilder returnValue = context.GetMethodGenerator.DeclareLocal(context.Property.PropertyType); context.GetMethodGenerator.Emit(OpCodes.Stloc, returnValue); // Call inspector(layer, PropertyInfo, value) context.GetMethodGenerator.Emit(OpCodes.Ldarg_0); context.GetMethodGenerator.Emit(OpCodes.Ldsfld, context.PropertyInfoField); context.GetMethodGenerator.Emit(OpCodes.Ldloc, returnValue); if (context.Property.PropertyType.IsValueType) { context.GetMethodGenerator.Emit(OpCodes.Box, context.Property.PropertyType); } // Allow inspector be generic in property type getInspector = getInspector.Specialize(context.BaseClass, typeof(void), typeof(PropertyInfo), context.Property.PropertyType); context.GetMethodGenerator.EmitCall(OpCodes.Call, getInspector, null); // Load real return value to leave stack unchanged context.GetMethodGenerator.Emit(OpCodes.Ldloc, returnValue); } }
/// <summary> /// Implements properties using getter and setter methods /// </summary> /// <param name="context"></param> /// <param name="initMethod"></param> /// <param name="getMethod"></param> /// <param name="setMethod"></param> private static void ImplementGetterAndSetter(PropertyBuilderContext context, MethodInfo initMethod, MethodInfo getMethod, MethodInfo setMethod) { // Define field to hold info for this prop FieldBuilder stateField = context.TypeBuilder.DefineField("__propertyState_" + context.Property.Name, initMethod.ReturnType, FieldAttributes.Private); // Append to Init method code to call our initializer and store output in field context.InitMethodGenerator.Emit(OpCodes.Ldarg_0); context.InitMethodGenerator.Emit(OpCodes.Ldarg_0); context.InitMethodGenerator.Emit(OpCodes.Ldsfld, context.PropertyInfoField); context.InitMethodGenerator.EmitCall(OpCodes.Call, initMethod, null); context.InitMethodGenerator.Emit(OpCodes.Stfld, stateField); // Call getter method if (context.GetMethodGenerator != null) { context.GetMethodGenerator.Emit(OpCodes.Ldarg_0); context.GetMethodGenerator.Emit(OpCodes.Ldarg_0); context.GetMethodGenerator.Emit(OpCodes.Ldfld, stateField); getMethod = getMethod.Specialize(context.BaseClass, typeof(object), stateField.FieldType); context.GetMethodGenerator.EmitCall(OpCodes.Call, getMethod, null); if (context.Property.PropertyType.IsValueType && !getMethod.ReturnType.IsValueType) { context.GetMethodGenerator.Emit(OpCodes.Unbox_Any, context.Property.PropertyType); } else if (!context.Property.PropertyType.IsValueType && getMethod.ReturnType.IsValueType) { context.GetMethodGenerator.Emit(OpCodes.Box); } } // Call setter method if (context.SetMethodGenerator != null) { context.SetMethodGenerator.Emit(OpCodes.Ldarg_0); // Instance for handler call context.SetMethodGenerator.Emit(OpCodes.Ldarg_0); // Instance for field context.SetMethodGenerator.Emit(OpCodes.Ldfld, stateField); // Info field context.SetMethodGenerator.Emit(OpCodes.Ldarg_1); // Value from set method setMethod = setMethod.Specialize(context.BaseClass, typeof(void), stateField.FieldType, context.Property.PropertyType); // If prop is value type but handler takes object, we must box if (context.Property.PropertyType.IsValueType && !setMethod.GetParameters().Last().ParameterType.IsValueType) { context.SetMethodGenerator.Emit(OpCodes.Box, context.Property.PropertyType); } context.SetMethodGenerator.EmitCall(OpCodes.Call, setMethod, null); } }
/// <summary> /// Implements a property using a private backing field /// </summary> /// <param name="context"></param> private static void ImplementBackingField(PropertyBuilderContext context) { // Define field to hold info for this prop FieldBuilder valueField = context.TypeBuilder.DefineField("__backingField_" + context.Property.Name, context.Property.PropertyType, FieldAttributes.Private); if (context.GetMethodGenerator != null) { context.GetMethodGenerator.Emit(OpCodes.Ldarg_0); context.GetMethodGenerator.Emit(OpCodes.Ldfld, valueField); } if (context.SetMethodGenerator != null) { context.SetMethodGenerator.Emit(OpCodes.Ldarg_0); context.SetMethodGenerator.Emit(OpCodes.Ldarg_1); context.SetMethodGenerator.Emit(OpCodes.Stfld, valueField); } }
private static void ImplementSetInspector(PropertyBuilderContext context, Action <PropertyBuilderContext> implement, MethodInfo preSetInspector, MethodInfo postSetInspector) { // Call pre set inspector if (preSetInspector != null && context.SetMethodGenerator != null) { context.SetMethodGenerator.Emit(OpCodes.Ldarg_0); context.SetMethodGenerator.Emit(OpCodes.Ldsfld, context.PropertyInfoField); context.SetMethodGenerator.Emit(OpCodes.Ldarg_1); preSetInspector = preSetInspector.Specialize(context.BaseClass, typeof(void), typeof(PropertyInfo), context.Property.PropertyType); if (context.Property.PropertyType.IsValueType && !preSetInspector.GetParameters().Last().ParameterType.IsValueType) { context.SetMethodGenerator.Emit(OpCodes.Box, context.Property.PropertyType); } context.SetMethodGenerator.EmitCall(OpCodes.Call, preSetInspector, null); } // Run real implementor now implement(context); // Call post set if (context.SetMethodGenerator != null && postSetInspector != null) { // Call inspector(layer, PropertyInfo, value) context.SetMethodGenerator.Emit(OpCodes.Ldarg_0); context.SetMethodGenerator.Emit(OpCodes.Ldsfld, context.PropertyInfoField); context.SetMethodGenerator.Emit(OpCodes.Ldarg_1); // Allow inspector be generic in property type postSetInspector = postSetInspector.Specialize(context.BaseClass, typeof(void), typeof(PropertyInfo), context.Property.PropertyType); if (context.Property.PropertyType.IsValueType && !postSetInspector.GetParameters().Last().ParameterType.IsValueType) { context.SetMethodGenerator.Emit(OpCodes.Box, context.Property.PropertyType); } context.SetMethodGenerator.EmitCall(OpCodes.Call, postSetInspector, null); } }