/// <summary> /// Intializes a new instance of the <see cref="InheritedEvent"/> class. /// </summary> /// <param name="engine">The code generation engine.</param> /// <param name="eventInfo">Event the type in creation has inherited.</param> internal InheritedEvent(CodeGenEngine engine, EventInfo eventInfo) : base(engine) { mEventInfo = eventInfo; mAddAccessor = new InheritedMethod(engine, mEventInfo.GetAddMethod(true)); mRemoveAccessor = new InheritedMethod(engine, mEventInfo.GetRemoveMethod(true)); Freeze(); }
/// <summary> /// Intializes a new instance of the <see cref="GeneratedProperty"/> class. /// </summary> /// <param name="engine">The code generation engine.</param> /// <param name="property">Property the type in creation has inherited.</param> internal InheritedProperty(CodeGenEngine engine, PropertyInfo property) : base(engine) { mPropertyInfo = property; // init get accessor method MethodInfo getAccessor = mPropertyInfo.GetGetMethod(true); if (getAccessor != null) { mGetAccessorMethod = new InheritedMethod(engine, getAccessor); } // init set accessor method MethodInfo setAccessor = mPropertyInfo.GetSetMethod(true); if (setAccessor != null) { mSetAccessorMethod = new InheritedMethod(engine, setAccessor); } Freeze(); }
/// <summary> /// Intializes a new instance of the <see cref="GeneratedMethod"/> class (for overrides). /// </summary> /// <param name="engine">The code generation engine.</param> /// <param name="method">Inherited method to override.</param> internal GeneratedMethod(CodeGenEngine engine, InheritedMethod method) : base(engine) { if (method == null) { throw new ArgumentNullException(nameof(method)); } mName = method.Name; mKind = MethodKind.Override; mReturnType = method.ReturnType; mParameterTypes = new List <Type>(method.ParameterTypes); mVisibility = method.Visibility; mCallingConvention = method.MethodInfo.CallingConvention; mMethodAttributes = method.MethodInfo.Attributes; mMethodAttributes &= ~MethodAttributes.Abstract; mMethodAttributes &= ~MethodAttributes.NewSlot; mMethodAttributes |= MethodAttributes.ReuseSlot; // do not allow changes to overridden methods // (signature must match the signature of the inherited method) Freeze(); }
/// <summary> /// Implements the event. /// </summary> /// <param name="engine">The <see cref="CodeGenEngine"/> assembling the type in creation.</param> /// <param name="property">The property to implement.</param> public void Implement(CodeGenEngine engine, GeneratedProperty property) { ILGenerator getMsil = property.GetAccessor.MethodBuilder?.GetILGenerator(); ILGenerator setMsil = property.SetAccessor.MethodBuilder?.GetILGenerator(); // implement get accessor // --------------------------------------------------------------------------------------------------------------- if (getMsil != null) { if (property.Kind == PropertyKind.Static) { getMsil.Emit(OpCodes.Ldsfld, mBackingField.FieldBuilder); } else { getMsil.Emit(OpCodes.Ldarg_0); getMsil.Emit(OpCodes.Ldfld, mBackingField.FieldBuilder); } getMsil.Emit(OpCodes.Ret); } // implement set accessor // --------------------------------------------------------------------------------------------------------------- if (setMsil != null) { MethodInfo equalsMethod = typeof(object).GetMethod("Equals", new Type[] { typeof(object), typeof(object) }); Label endLabel = setMsil.DefineLabel(); // jump to end, if the value to set equals the backing field if (property.Kind == PropertyKind.Static) { setMsil.Emit(OpCodes.Ldsfld, mBackingField.FieldBuilder); if (property.Type.IsValueType) { setMsil.Emit(OpCodes.Box, property.Type); } setMsil.Emit(OpCodes.Ldarg_0); if (property.Type.IsValueType) { setMsil.Emit(OpCodes.Box, property.Type); } } else { setMsil.Emit(OpCodes.Ldarg_0); setMsil.Emit(OpCodes.Ldfld, mBackingField.FieldBuilder); if (property.Type.IsValueType) { setMsil.Emit(OpCodes.Box, property.Type); } setMsil.Emit(OpCodes.Ldarg_1); if (property.Type.IsValueType) { setMsil.Emit(OpCodes.Box, property.Type); } } setMsil.Emit(OpCodes.Call, equalsMethod); setMsil.Emit(OpCodes.Brtrue_S, endLabel); // update field if (property.Kind == PropertyKind.Static) { setMsil.Emit(OpCodes.Ldarg_0); setMsil.Emit(OpCodes.Stsfld, mBackingField.FieldBuilder); } else { setMsil.Emit(OpCodes.Ldarg_0); setMsil.Emit(OpCodes.Ldarg_1); setMsil.Emit(OpCodes.Stfld, mBackingField.FieldBuilder); } // call event raiser if (property.Kind != PropertyKind.Static) { IMethod raiserMethod = engine.GetMethod("OnPropertyChanged", new Type[] { typeof(string) }); if (raiserMethod == null) { string error = string.Format( "The class ({0}) or its base class ({1}) does not define 'void OnPropertyChanged(string name)'.", engine.TypeBuilder.FullName, engine.TypeBuilder.BaseType.FullName); sLog.Write(LogLevel.Error, error); throw new CodeGenException(error); } if (raiserMethod is GeneratedMethod) { GeneratedMethod method = raiserMethod as GeneratedMethod; setMsil.Emit(OpCodes.Ldarg_0); setMsil.Emit(OpCodes.Ldstr, property.Name); setMsil.Emit(OpCodes.Callvirt, method.MethodBuilder); if (method.ReturnType != typeof(void)) { setMsil.Emit(OpCodes.Pop); } } else if (raiserMethod is InheritedMethod) { InheritedMethod method = raiserMethod as InheritedMethod; setMsil.Emit(OpCodes.Ldarg_0); setMsil.Emit(OpCodes.Ldstr, property.Name); setMsil.Emit(OpCodes.Callvirt, method.MethodInfo); if (method.ReturnType != typeof(void)) { setMsil.Emit(OpCodes.Pop); } } else { throw new NotImplementedException("Method is neither generated nor inherited."); } } setMsil.MarkLabel(endLabel); setMsil.Emit(OpCodes.Ret); } }