Beispiel #1
0
 protected virtual void EmitPlainCompositeHashCode(
     CompositeCodeGenerationInfo codeGenerationInfo,
     CompositeModel compositeModel,
     CompositeTypeModel typeModel,
     CompositeTypeGenerationInfo publicCompositeGenInfo,
     CompositeTypeGenerationInfo thisGenInfo,
     CompositeEmittingInfo emittingInfo,
     IEnumerable <FragmentTypeGenerationInfo> fragmentGenerationInfos
     )
 {
     this.EmitCallNonCompositeMethod(
         codeGenerationInfo,
         compositeModel,
         typeModel,
         publicCompositeGenInfo,
         thisGenInfo,
         emittingInfo,
         fragmentGenerationInfos,
         HASH_CODE_METHOD,
         null,
         null,
         genInfos => genInfos.FirstOrDefault(genInfo =>
     {
         var result = thisGenInfo.Parents.Keys.Where(t => !thisGenInfo.Builder.Equals(t)).OnlyBottomTypes().Where(t => !OBJECT_TYPE.Equals(t)).Any(p => genInfo.Parents.ContainsKey(p.GenericDefinitionIfGArgsHaveGenericParams())) ||
                      genInfo.DirectBaseFromModel.GetFullInheritanceChain().Any(t => compositeModel.ApplicationModel.GenericFragmentBaseType.NewWrapperAsType(this.ctx).Equals(t));
         if (result)
         {
             var m  = TypeGenerationUtils.FindMethodImplicitlyImplementingMethod(genInfo.DirectBaseFromModel, HASH_CODE_METHOD);
             result = !HASH_CODE_METHOD.Equals(m);
         }
         return(result);
     })
         );
 }
        private static TMethod GetMethodBase <TMethod>(CILTypeBase propType, TMethod method, TypeGenerationInfo thisGenInfo)
            where TMethod : CILMethodBase
        {
            var declType = method.DeclaringType;

            return(TypeGenerationUtils.GetMethodForEmitting(t => TypeGenerationUtils.CreateTypeForEmittingCILType(TypeGenerationUtils.GenericDefinitionIfGArgsHaveGenericParams(declType).MakeGenericType(propType.GetGenericArgumentsArray()), thisGenInfo.GenericArguments, null), method));
            //var declType = method.DeclaringType;
            //return propType.ContainsGenericParameters() ?
            //   TypeGenerationUtils.GetMethodForEmitting( type => TypeGenerationUtils.CreateTypeForEmitting( declType.IsGenericType ?
            //      declType.GetGenericTypeDefinition().MakeGenericType( propType.GetGenericArguments() ) :
            //      declType, thisGenInfo.GenericArguments, null ), method ) :
            //   (TMethod) MethodBase.GetMethodFromHandle( method.MethodHandle, ( declType.IsGenericType ?
            //      declType.GetGenericTypeDefinition().MakeGenericType( propType.GetGenericArguments() ) :
            //      declType ).TypeHandle );
        }
Beispiel #3
0
        protected virtual void EmitPlainCompositeEquals(
            CompositeCodeGenerationInfo codeGenerationInfo,
            CompositeModel compositeModel,
            CompositeTypeModel typeModel,
            CompositeTypeGenerationInfo publicCompositeGenInfo,
            CompositeTypeGenerationInfo thisGenInfo,
            CompositeEmittingInfo emittingInfo,
            IEnumerable <FragmentTypeGenerationInfo> fragmentGenerationInfos
            )
        {
            // return Object.ReferenceEquals(this, obj) || (obj is <composite type> && <equals-implementation>);
            ILLabel?returnTrueL  = null;
            ILLabel?returnFalseL = null;

            this.EmitCallNonCompositeMethod(
                codeGenerationInfo,
                compositeModel,
                typeModel,
                publicCompositeGenInfo,
                thisGenInfo,
                emittingInfo,
                fragmentGenerationInfos,
                EQUALS_METHOD,
                il =>
            {
                // Make labels for true and false values
                returnTrueL  = il.DefineLabel();
                returnFalseL = il.DefineLabel();

                il.EmitLoadArg(0)
                .EmitLoadArg(1)
                .EmitCall(REFERENCE_EQUALS_METHOD)
                .EmitBranch(BranchType.IF_TRUE, returnTrueL.Value);

                var continueLabel = il.DefineLabel();
                foreach (var parent in thisGenInfo.Parents.Values.OnlyBottomTypes())
                {
                    il.EmitLoadArg(1)
                    .EmitIsInst(parent)
                    .EmitBranch(BranchType.IF_TRUE, continueLabel);
                }
                il.EmitBranch(BranchType.ALWAYS, returnFalseL.Value)
                .MarkLabel(continueLabel);
            },
                il =>
            {
                // return true
                il.MarkLabel(returnTrueL.Value)
                .EmitLoadBoolean(true)
                .EmitReturn()

                // return false
                .MarkLabel(returnFalseL.Value)
                .EmitLoadBoolean(false)
                .EmitReturn();
            },
                genInfos => genInfos.FirstOrDefault(genInfo =>
            {
                var result = thisGenInfo.Parents.Keys.Where(t => !thisGenInfo.Builder.Equals(t)).OnlyBottomTypes().Where(t => !OBJECT_TYPE.Equals(t)).Any(p => genInfo.Parents.ContainsKey(p.GenericDefinitionIfGArgsHaveGenericParams())) ||
                             genInfo.DirectBaseFromModel.GetFullInheritanceChain().Any(t => compositeModel.ApplicationModel.GenericFragmentBaseType.NewWrapperAsType(this.ctx).Equals(t));
                if (result)
                {
                    var m  = TypeGenerationUtils.FindMethodImplicitlyImplementingMethod(genInfo.DirectBaseFromModel, EQUALS_METHOD);
                    result = !EQUALS_METHOD.Equals(m);
                }
                return(result);
            })
                );
        }
        protected virtual void EmitLoadDefaultValueForPropertyModel(
            PropertyModel propModel,
            CompositeTypeGenerationInfo propertyDeclaringTypeGenInfo,
            MethodGenerationInfo methodGenInfo
            )
        {
            var il       = methodGenInfo.IL;
            var pInfo    = propModel.NativeInfo.NewWrapper(this.ctx);
            var propType = propertyDeclaringTypeGenInfo.AutoGeneratedPropertyInfos[propModel.NativeInfo].PropertyType;
            var declType = pInfo.DeclaringType;
            UseDefaultsAttribute udAttr;

            if (propModel.DefaultValueCreator != null)
            {
                // Get creator from property model
                il.EmitLoadLocal(methodGenInfo.GetLocalOrThrow(LB_C_INSTANCE))
                .EmitCall(MODEL_INFO_GETTER)
                .EmitCall(MODEL_GETTER)
                .EmitCall(C_METHODS_GETTER)
                .EmitLoadInt32(propModel.GetterMethod.MethodIndex)
                .EmitCall(COMPOSITE_METHODS_INDEXER)
                .EmitCall(PROPERTY_MODEL_GETTER)
                .EmitCall(DEFAULT_CREATOR_GETTER);
                if (WillDefaultValueCreatorParameterBeNull(pInfo))
                {
                    il.EmitLoadNull();
                }
                else
                {
                    il.EmitReflectionObjectOf(propertyDeclaringTypeGenInfo.Parents[declType])
                    .EmitLoadString(pInfo.Name)
                    .EmitCall(GET_PROPERTY_INFO_METHOD);
                }
                il
                .EmitLoadLocal(methodGenInfo.GetLocalOrThrow(LB_C_INSTANCE))
                .EmitCall(STRUCTURE_OWNER_GETTER_METHOD)
                .EmitCall(APPLICATION_GETTER_METHOD)
                .EmitCall(DEFAULT_CREATOR_INVOKER)
                .EmitCastToType(DEFAULT_CREATOR_INVOKER.GetReturnType(), TypeGenerationUtils.CreateTypeForEmitting(propType, propertyDeclaringTypeGenInfo.GenericArguments, null));
            }
            else if (propModel.IsUseDefaults(out udAttr))
            {
                var propTypeGDef = propModel.NativeInfo.PropertyType.GetGenericDefinitionIfGenericType();
                System.Reflection.MethodBase defaultValueCtor;
                CILTypeBase nullableParameter;
                if (propType.IsNullable(out nullableParameter))
                {
                    il.EmitLoadDefault(nullableParameter, aType => methodGenInfo.GetOrCreateLocalBasedOnType(aType))
                    .EmitNewObject(GetMethodBase(propType, NULLABLE_CTOR, propertyDeclaringTypeGenInfo));
                }
                else if (STRING_TYPE.Equals(propType))
                {
                    il.EmitLoadString(DEFAULT_STRING);
                }
                else if (DEFAULT_CREATORS.TryGetValue(propTypeGDef, out defaultValueCtor))
                {
                    if (udAttr.ActualType != null)
                    {
                        var otherCtor = udAttr.ActualType
                                        .GetConstructors(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)
                                        .FirstOrDefault(ctor => ctor.GetParameters().Length == 0);
                        if (otherCtor != null)
                        {
                            defaultValueCtor = otherCtor;
                        }
                    }
                    if (defaultValueCtor is System.Reflection.ConstructorInfo)
                    {
                        il.EmitNewObject(GetMethodBase(propType, ((System.Reflection.ConstructorInfo)defaultValueCtor).NewWrapper(this.ctx), propertyDeclaringTypeGenInfo));
                    }
                    else if (defaultValueCtor is System.Reflection.MethodInfo)
                    {
                        if (((System.Reflection.MethodInfo)defaultValueCtor).IsStatic)
                        {
                            il.EmitCall(GetMethodBase(propType, ((System.Reflection.MethodInfo)defaultValueCtor).NewWrapper(this.ctx), propertyDeclaringTypeGenInfo));
                        }
                        else
                        {
                            throw new InternalException("The default creators contained non-static method for type " + propTypeGDef + ".");
                        }
                    }
                    else
                    {
                        throw new InternalException("Unknown default value creator " + defaultValueCtor + ".");
                    }
                }
                else if (propType.IsArray() || IENUMERABLE_GDEF_TYPE.Equals(TypeGenerationUtils.GenericDefinitionIfGArgsHaveGenericParams(propType as CILType)))  // || IENUMERABLE_NO_GDEF_TYPE.Equals( propType ) )
                {
                    var elementType = propType.IsArray() ? ((CILType)propType).ElementType : /*( IENUMERABLE_NO_GDEF_TYPE.Equals( propType ) ? OBJECT_TYPE :*/ ((CILType)propType).GenericArguments[0] /* )*/;
                    il.EmitLoadInt32(0)
                    .EmitNewArray(TypeGenerationUtils.CreateTypeForEmitting(elementType, propertyDeclaringTypeGenInfo.GenericArguments, null));
                }
                else if (!propType.IsValueType())
                {
                    var ctorType          = udAttr.ActualType == null ? (CILType)propType : udAttr.ActualType.NewWrapperAsType(this.ctx);
                    var eDefaultValueCtor = ctorType.Constructors.FirstOrDefault(ctor => !ctor.Parameters.Any());
                    if (eDefaultValueCtor != null)
                    {
                        il.EmitNewObject(GetMethodBase(ctorType, eDefaultValueCtor, propertyDeclaringTypeGenInfo));
                    }
                    else
                    {
                        throw new NotSupportedException("Tried to use " + USE_DEFAULTS_ATTRIBUTE_TYPE + " on a type (" + ctorType + ") with no parameterless constructor.");
                    }
                }
                else
                {
                    throw new InternalException("Could not emit default value for " + pInfo.GetPropertyType() + ".");
                }
            }
        }
        protected virtual void EmitPropertyRelatedThings(
            CompositeCodeGenerationInfo codeGenerationInfo,
            CompositeTypeGenerationInfo publicCompositeGenInfo,
            CompositeTypeGenerationInfo thisGenerationInfo,
            CompositeMethodGenerationInfo thisMethodGenerationInfo,
            PropertyModel propertyModel,
            Type genericPropertyMixinType
            )
        {
            var nPropertyInfo = propertyModel.NativeInfo;
            var propertyInfo  = nPropertyInfo.NewWrapper(this.ctx);

            if (this.IsCompositeGeneratedProperty(thisGenerationInfo, propertyModel, genericPropertyMixinType))
            {
                var propertyIdx  = thisGenerationInfo.AutoGeneratedPropertyInfos.Count;
                var propertyType = TypeGenerationUtils.CreateTypeForEmitting(propertyInfo.GetPropertyType(), thisGenerationInfo.GenericArguments, null);

                CILTypeBase fieldType;
                Action <CILField, MethodIL> readMethod;
                Action <CILField, MethodIL> read32Method;
                Action <CILField, MethodIL> writeMethod;
                Action <CILField, MethodIL> compareExchangeMethodEmitter;
                this.GetReadAndWriteMethods(propertyType, out readMethod, out read32Method, out writeMethod, out compareExchangeMethodEmitter, out fieldType);

                // Field:
                // private <property type or Object> _property<idx>;
                var propertyField = thisGenerationInfo.Builder.AddField(
                    PROPERTY_FIELD_PREFIX + propertyIdx,
                    fieldType,
                    FieldAttributes.Private
                    );

                // Field getter
                var getter = thisGenerationInfo.Builder.AddMethod(
                    PROPERTY_METHOD_PREFIX + propertyIdx + PROPERTY_GETTER_POSTFIX,
                    MethodAttributes.Private | MethodAttributes.HideBySig,
                    CallingConventions.HasThis);
                this.EmitPropertyGetterMethod(codeGenerationInfo, propertyModel, publicCompositeGenInfo, thisGenerationInfo, propertyField, propertyType, (CompositeMethodGenerationInfo) new CompositeMethodGenerationInfoImpl(getter, null, null).WithReturnType(propertyType) /*.WithParameters( propertyInfo.GetIndexParameters().Select( p => Tuple.Create( p.ParameterType, p.Attributes ) ) )*/, readMethod);

                // Field getter for 32-bit processes, if required
                CILMethod getter32 = null;
                if (read32Method != null)
                {
                    getter32 = thisGenerationInfo.Builder.AddMethod(
                        PROPERTY_METHOD_PREFIX + propertyIdx + PROPERTY_GETTER32_POSTFIX,
                        MethodAttributes.Private | MethodAttributes.HideBySig,
                        CallingConventions.HasThis);
                    this.EmitPropertyGetterMethod(codeGenerationInfo, propertyModel, publicCompositeGenInfo, thisGenerationInfo, propertyField, propertyType, (CompositeMethodGenerationInfo) new CompositeMethodGenerationInfoImpl(getter32, null, null).WithReturnType(propertyType) /*.WithParameters( propertyInfo.GetIndexParameters().Select( p => Tuple.Create( p.ParameterType, p.Attributes ) ) )*/, read32Method);
                }
                // Field setter
                var setter = thisGenerationInfo.Builder.AddMethod(
                    PROPERTY_METHOD_PREFIX + propertyIdx + PROPERTY_SETTER_POSTFIX,
                    MethodAttributes.Public | MethodAttributes.HideBySig, // TODO MethodAttributes.Assembly when [InternalsVisibleTo(...)] attribute will be applied to all generated assemblies.
                    CallingConventions.HasThis);
                this.EmitPropertySetterMethod(codeGenerationInfo, propertyModel, publicCompositeGenInfo, thisGenerationInfo, propertyField, fieldType, propertyType, (CompositeMethodGenerationInfo) new CompositeMethodGenerationInfoImpl(setter, null, null).WithParameters(Enumerable.Repeat(Tuple.Create(propertyType, ParameterAttributes.None), 1)), writeMethod);

                // Exchange method
                var exchangeMethod = thisGenerationInfo.Builder.AddMethod(
                    PROPERTY_METHOD_PREFIX + propertyIdx + PROPERTY_EXCHANGE_POSTFIX,
                    MethodAttributes.Private | MethodAttributes.HideBySig,
                    CallingConventions.HasThis);
                this.EmitPropertyExchangeMethod(propertyModel, thisGenerationInfo, propertyField, fieldType, propertyType, setter, (CompositeMethodGenerationInfo) new CompositeMethodGenerationInfoImpl(exchangeMethod, null, null).WithReturnType(propertyType).WithParameters(Enumerable.Repeat(Tuple.Create(propertyType, ParameterAttributes.None), 1)), writeMethod);

                // CompareExchange method
                var compareExchangeMethod = thisGenerationInfo.Builder.AddMethod(
                    PROPERTY_METHOD_PREFIX + propertyIdx + PROPERTY_COMPARE_EXCHANGE_POSTFIX,
                    MethodAttributes.Private | MethodAttributes.HideBySig,
                    CallingConventions.HasThis);
                this.EmitPropertyCompareExchangeMethod(propertyModel, thisGenerationInfo, propertyField, (CompositeMethodGenerationInfo) new CompositeMethodGenerationInfoImpl(compareExchangeMethod, null, null).WithReturnType(propertyType).WithParameters(Enumerable.Repeat(Tuple.Create(propertyType, ParameterAttributes.None), 2)), compareExchangeMethodEmitter);

                thisGenerationInfo.AutoGeneratedPropertyInfos.Add(nPropertyInfo, new PropertyGenerationInfo(
                                                                      this.EmitRefMethodForPropertyOrEvent(propertyField, PROPERTY_METHOD_PREFIX + propertyIdx + REF_INVOKER_METHOD_SUFFIX),
                                                                      propertyModel,
                                                                      propertyField,
                                                                      getter,
                                                                      getter32,
                                                                      setter,
                                                                      exchangeMethod,
                                                                      compareExchangeMethod,
                                                                      propertyType
                                                                      ));
            }

            if (this.NeedToEmitAdditionalMemberInfo(thisGenerationInfo, propertyInfo.Name, (parent, name) => parent.DeclaredProperties.FirstOrDefault(p => Object.Equals(p.Name, name))))
            {
                // Need to define property if we inherit property directly from interface
                var name = propertyInfo.Name;
                if (thisGenerationInfo.RawPropertyInfos.Keys.Any(pInfo => pInfo.Name.Equals(name)))
                {
                    // We already have property with the same name from different type
                    name = QualifiedName.FromMemberInfo(nPropertyInfo).ToString();
                }

                CILProperty pBuilder;
                if (!thisGenerationInfo.RawPropertyInfos.TryGetValue(nPropertyInfo, out pBuilder))
                {
                    pBuilder = thisGenerationInfo.Builder.AddProperty(
                        name,
                        propertyInfo.Attributes
                        );
                    thisGenerationInfo.RawPropertyInfos.Add(nPropertyInfo, pBuilder);
                }

                if (thisMethodGenerationInfo.MethodFromModel.Equals(propertyInfo.GetMethod))
                {
                    pBuilder.GetMethod = thisMethodGenerationInfo.Builder;
                }
                else if (thisMethodGenerationInfo.MethodFromModel.Equals(propertyInfo.SetMethod))
                {
                    pBuilder.SetMethod = thisMethodGenerationInfo.Builder;
                }
                else
                {
                    throw new InternalException("Found a property, but neither setter nor getter matched the method being emitted. Property is " + propertyInfo + ", method is " + thisMethodGenerationInfo.MethodFromModel + ".");
                }
            }
        }
Beispiel #6
0
        protected virtual void EmitEventInvocationMethodCore(
            EventModel eventModel,
            CompositeTypeGenerationInfo thisGenerationInfo,
            CILField eventField,
            CILTypeBase fieldType,
            CompositeMethodGenerationInfo invokeMethod,
            CILMethod eventMethodToInvoke,
            Action <LocalBuilder, EventInvocation, Type> actualEventInvoking
            )
        {
            var eventInfo = eventModel.NativeInfo;
            var il        = invokeMethod.IL;

            var eventLB             = il.DeclareLocal(fieldType);
            var afterNullCheckLabel = il.DefineLabel();

            il
            .EmitLoadThisField(eventField)
            .EmitStoreLocal(eventLB)
            .EmitLoadLocal(eventLB)
            .EmitBranch(BranchType.IF_FALSE, afterNullCheckLabel);

            EventInvocation invocationStyle;
            Type            exceptionType;

            this.GetEventInvocationStyle(eventModel, out invocationStyle, out exceptionType);

            actualEventInvoking(eventLB, invocationStyle, exceptionType);

            // Throw exception if needed
            if (EventInvocation.INVOKE_ALL.Equals(invocationStyle))
            {
                // TODO TODO TODO
                this.EmitThrowIfExceptionListHasAny(invokeMethod, exceptionType.GetConstructor(EXCEPTION_ENUMERABLE_ARRAY).NewWrapper(this.ctx));
            }

            if (!VOID_TYPE.Equals(eventMethodToInvoke.GetReturnType()))
            {
                //LocalBuilder amountOfDeadB;
                //if ( invokeMethod.TryGetLocal( LB_AMOUNT_OF_DEAD_EVENT_INFOS, out amountOfDeadB ) )
                //{
                //   il
                //      .EmitLoadLocal( amountOfDeadB )
                //      .EmitBranch( BranchType.IF_FALSE, afterNullCheckLabel );
                //}
                LocalBuilder resultB;
                if (invokeMethod.TryGetLocal(LB_RESULT, out resultB))
                {
                    il.EmitLoadLocal(resultB);
                }
                var returnLabel = il.DefineLabel();
                il
                .EmitBranch(BranchType.ALWAYS, returnLabel)
                .MarkLabel(afterNullCheckLabel)
                .EmitLoadString("The event " + eventInfo.Name + " in ")
                .EmitReflectionObjectOf(TypeGenerationUtils.CreateTypeForEmitting(eventInfo.DeclaringType.NewWrapper(this.ctx), thisGenerationInfo.GenericArguments, null))
                .EmitCall(TO_STRING_METHOD)
                .EmitLoadString(" is not set.")
                .EmitCall(STRING_CONCAT_METHOD_3)
                .EmitThrowNewException(INVALID_OPERATION_EXCEPTION_CTOR_WITH_STRING)
                .MarkLabel(returnLabel);
            }
            else
            {
                il.MarkLabel(afterNullCheckLabel);
            }

            il.EmitReturn();
        }
Beispiel #7
0
        protected virtual void EmitEventRelatedThings(
            CompositeTypeGenerationInfo thisGenerationInfo,
            CompositeMethodGenerationInfo thisMethodGenerationInfo,
            EventModel eventModel,
            Type genericEventMixinType
            )
        {
            var nEventInfo = eventModel.NativeInfo;
            var eventInfo  = nEventInfo.NewWrapper(this.ctx);
            CompositeMethodGenerationInfo invokeMethod = null;

            if (this.IsCompositeGeneratedEvent(thisGenerationInfo, eventModel, genericEventMixinType))
            {
                var eventIdx              = thisGenerationInfo.AutoGeneratedEventInfos.Count;
                var eventType             = TypeGenerationUtils.CreateTypeForEmitting(eventInfo.EventHandlerType, thisGenerationInfo.GenericArguments, null);
                var invokeMethodFromModel = eventModel.NativeInfo.EventHandlerType.GetMethod(DELEGATE_INVOKE_METHOD_NAME).NewWrapper(this.ctx);

                CILTypeBase fieldType;
                Action <CILField, MethodIL> addAction, removeAction;
                Action <EventModel, CompositeTypeGenerationInfo, CILField, CILTypeBase, CompositeMethodGenerationInfo, CILMethod> invokeAction;
                Action <CILField, MethodIL> checkAction;
                this.CreateEmittingActionsForEvent(
                    eventModel,
                    eventType,
                    out fieldType,
                    out addAction,
                    out removeAction,
                    out invokeAction,
                    out checkAction
                    );

                // Field:
                // private <field type> _event<idx>;
                var eventField = thisGenerationInfo.Builder.AddField(
                    EVENT_FIELD_PREFIX + eventIdx,
                    fieldType,
                    FieldAttributes.Private
                    );

                var addMethod = this.ImplementMethodForEmitting(
                    thisGenerationInfo,
                    eventModel.AddMethod.NativeInfo.NewWrapper(this.ctx),
                    EVENT_METHOD_PREFIX + eventIdx + EVENT_ADDITION_POSTFIX,
                    MethodAttributes.Private | MethodAttributes.HideBySig,
                    false
                    );
                this.EmitThrowIfApplicationNotActiveWithoutLocalVariable(thisGenerationInfo, addMethod.IL);
                addAction(eventField, addMethod.IL);

                CompositeMethodGenerationInfo removeMethod = this.ImplementMethodForEmitting(
                    thisGenerationInfo,
                    eventModel.RemoveMethod.NativeInfo.NewWrapper(this.ctx),
                    EVENT_METHOD_PREFIX + eventIdx + EVENT_REMOVAL_POSTFIX,
                    MethodAttributes.Private | MethodAttributes.HideBySig,
                    false
                    );
                this.EmitThrowIfApplicationNotActiveWithoutLocalVariable(thisGenerationInfo, removeMethod.IL);
                removeAction(eventField, removeMethod.IL);

                invokeMethod = this.ImplementMethodForEmitting(
                    thisGenerationInfo,
                    decType => TypeGenerationUtils.CreateTypeForEmittingCILType(decType, thisGenerationInfo.GenericArguments, null),
                    invokeMethodFromModel,
                    EVENT_METHOD_PREFIX + eventIdx + EVENT_INVOCATION_POSTFIX,
                    MethodAttributes.Private | MethodAttributes.HideBySig,
                    false);
                var eventMethodToInvoke = invokeMethod.OverriddenMethod;
                this.EmitThrowIfApplicationNotActiveWithoutLocalVariable(thisGenerationInfo, invokeMethod.IL);
                invokeAction(eventModel, thisGenerationInfo, eventField, eventType, invokeMethod, eventMethodToInvoke);

                // Field clearer method:
                // private void Event<idx>Clear()
                // {
                //   Interlocked.Exchange<TEvent>(ref this._event<idx>, null);
                // }
                var eventClearMB = thisGenerationInfo.Builder.AddMethod(
                    EVENT_METHOD_PREFIX + eventIdx + EVENT_CLEAR_POSTFIX,
                    MethodAttributes.Private | MethodAttributes.HideBySig,
                    CallingConventions.HasThis);
                var il = eventClearMB.MethodIL;


                this.EmitThrowIfApplicationNotActiveWithoutLocalVariable(thisGenerationInfo, il);

                il.EmitLoadThisFieldAddress(eventField);
                il.EmitLoadNull();
                il.EmitCall(INTERLOCKED_EXCHANGE_METHOD_GDEF.MakeGenericMethod(fieldType));
                il.EmitPop();
                il.EmitReturn();

                // Field checker method:
                // private Boolean Event<idx>Checker()
                // {
                //   // for strong refs
                //   return this._event<idx>;
                //   // for weak refs
                //   return
                // }
                var eventCheckerMB = thisGenerationInfo.Builder.AddMethod(
                    EVENT_METHOD_PREFIX + eventIdx + EVENT_CHECKER_POSTFIX,
                    MethodAttributes.Private | MethodAttributes.HideBySig,
                    CallingConventions.HasThis
                    );
                eventCheckerMB.ReturnParameter.ParameterType = BOOLEAN_TYPE;
                il = eventCheckerMB.MethodIL;

                this.EmitThrowIfApplicationNotActiveWithoutLocalVariable(thisGenerationInfo, il);
                checkAction(eventField, il);

                thisGenerationInfo.AutoGeneratedEventInfos.Add(
                    nEventInfo,
                    new EventGenerationInfo(
                        this.EmitRefMethodForPropertyOrEvent(eventField, EVENT_METHOD_PREFIX + eventIdx + REF_INVOKER_METHOD_SUFFIX),
                        eventModel,
                        eventType,
                        eventField,
                        addMethod.Builder,
                        removeMethod.Builder,
                        invokeMethod.Builder,
                        eventClearMB,
                        eventCheckerMB
                        )
                    );
            }

            if (this.NeedToEmitAdditionalMemberInfo(thisGenerationInfo, eventInfo.Name, (parent, name) => parent.DeclaredEvents.FirstOrDefault(evt => Object.Equals(evt.Name, name))))
            {
                // Need to define event if we inherit property directly from interface
                var name = eventInfo.Name;
                if (thisGenerationInfo.RawPropertyInfos.Keys.Any(pInfo => pInfo.Name.Equals(name)))
                {
                    // We already have event with the same name from different type
                    name = QualifiedName.FromMemberInfo(nEventInfo).ToString();
                }

                CILEvent eBuilder;
                if (!thisGenerationInfo.RawEventInfos.TryGetValue(nEventInfo, out eBuilder))
                {
                    eBuilder = thisGenerationInfo.Builder.AddEvent(
                        name,
                        eventInfo.Attributes,
                        TypeGenerationUtils.CreateTypeForEmitting(eventInfo.EventHandlerType, thisGenerationInfo.GenericArguments, null)
                        );
                    if (invokeMethod != null)
                    {
                        eBuilder.RaiseMethod = invokeMethod.Builder;
                    }
                    thisGenerationInfo.RawEventInfos.Add(nEventInfo, eBuilder);
                }

                if (thisMethodGenerationInfo.MethodFromModel.Equals(eventInfo.AddMethod))
                {
                    eBuilder.AddMethod = thisMethodGenerationInfo.Builder;
                }
                else if (thisMethodGenerationInfo.MethodFromModel.Equals(eventInfo.RemoveMethod))
                {
                    eBuilder.RemoveMethod = thisMethodGenerationInfo.Builder;
                }
                else
                {
                    throw new InternalException("Found an event, but neither adder nor remover methods matched the method being emitted. Event is " + eventInfo + ", method is " + thisMethodGenerationInfo.MethodFromModel + ".");
                }
            }
        }