/// <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();
        }
示例#3
0
        /// <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);
            }
        }