Exemplo n.º 1
0
        protected virtual void EmitThrowIfExceptionListHasAny(CompositeMethodGenerationInfo methodGenInfo, CILConstructor exceptionCtor)
        {
            var exceptionListB = methodGenInfo.GetLocalOrThrow(LB_EXCEPTION_LIST);
            var il             = methodGenInfo.IL;
            var noThrowLabel   = il.DefineLabel();

            il
            .EmitLoadLocal(exceptionListB)
            .EmitBranch(BranchType.IF_FALSE, noThrowLabel)
            .EmitLoadLocal(exceptionListB)
            .EmitThrowNewException(exceptionCtor)
            .MarkLabel(noThrowLabel);
        }
        protected virtual void EmitPropertyCompareExchangeMethod(
            PropertyModel propertyModel,
            CompositeTypeGenerationInfo thisGenerationInfo,
            CILField propertyField,
            CompositeMethodGenerationInfo methodGenInfo,
            Action <CILField, MethodIL> compareExchangeAction
            )
        {
            var il = methodGenInfo.IL;

            this.EmitThrowIfApplicationNotActiveWithoutLocalVariable(thisGenerationInfo, il);

            this.EmitCheckPropertyImmutability(propertyModel, thisGenerationInfo, il);

            // return Interlocked.CompareExchange(ref this._property, <arg-2>, <arg-1>);
            compareExchangeAction(propertyField, il);
            il.EmitReturn();
        }
        protected virtual void EmitPropertySetterMethod(
            CompositeCodeGenerationInfo codeGenerationInfo,
            PropertyModel propertyModel,
            CompositeTypeGenerationInfo publicCompositeGenInfo,
            CompositeTypeGenerationInfo thisGenerationInfo,
            CILField propertyField,
            CILTypeBase fieldType,
            CILTypeBase propertyType,
            CompositeMethodGenerationInfo methodGenInfo,
            Action <CILField, MethodIL> writeAction
            )
        {
            // Code for setting properties:
            // internal void Property<idx>Setter(<property type> value )
            // {
            //    CompositeInstance instance = this._instance;
            //    <if the property is immutable>
            //    if ( !this._instance.IsPrototype )
            //    {
            //       throw new InvalidOperationException( "Can not set immutable propery " + QualifiedName.FromTypeAndName( <declaring type>, <name> ) + " for a non-prototype composite instance." );
            //    }
            //    <end if>
            //    <write property field>
            // }
            var il = methodGenInfo.IL;

            il.EmitLoadThisField(thisGenerationInfo.CompositeField)
            .EmitStoreLocal(methodGenInfo.GetOrCreateLocal(LB_C_INSTANCE, codeGenerationInfo.CompositeInstanceFieldType.NewWrapper(this.ctx)));

            this.EmitThrowIfApplicationNotActive(methodGenInfo);

            this.EmitProcessParameters(codeGenerationInfo, propertyModel.SetterMethod, true, publicCompositeGenInfo, thisGenerationInfo, methodGenInfo);

            this.EmitThrowIfViolations(thisGenerationInfo, methodGenInfo, propertyModel.SetterMethod);

            this.EmitCheckPropertyImmutability(propertyModel, thisGenerationInfo, il);

            writeAction(propertyField, il);

            il
            .EmitPop()
            .EmitReturn();
        }
        protected virtual void EmitPropertyExchangeMethod(
            PropertyModel propertyModel,
            CompositeTypeGenerationInfo thisGenerationInfo,
            CILField propertyField,
            CILTypeBase fieldType,
            CILTypeBase propertyType,
            CILMethod propertySetter,
            CompositeMethodGenerationInfo methodGenInfo,
            Action <CILField, MethodIL> exchangeAction
            )
        {
            var il = methodGenInfo.IL;

            this.EmitThrowIfApplicationNotActiveWithoutLocalVariable(thisGenerationInfo, il);

            this.EmitCheckPropertyImmutability(propertyModel, thisGenerationInfo, il);

            exchangeAction(propertyField, il);
            il
            .EmitCastToType(fieldType, propertyType)
            .EmitReturn();
        }
        protected virtual void EmitPropertyGetterMethod(
            CompositeCodeGenerationInfo codeGenerationInfo,
            PropertyModel propertyModel,
            CompositeTypeGenerationInfo publicCompositeGenInfo,
            CompositeTypeGenerationInfo thisGenerationInfo,
            CILField propertyField,
            CILTypeBase propertyType,
            CompositeMethodGenerationInfo methodGenInfo,
            Action <CILField, MethodIL> readAction
            )
        {
            // Code for getting properties:
            // public <property type> Property<idx>Getter( )
            // {
            //    CompositeInstance instance = this._instance;
            //    <check application active>
            //    var result = <read property field>;
            //    <check constraints>
            //    return result;
            // }
            var il = methodGenInfo.IL;

            il.EmitLoadThisField(thisGenerationInfo.CompositeField)
            .EmitStoreLocal(methodGenInfo.GetOrCreateLocal(LB_C_INSTANCE, codeGenerationInfo.CompositeInstanceFieldType.NewWrapper(this.ctx)));
            this.EmitThrowIfApplicationNotActive(methodGenInfo);

            var resultB = methodGenInfo.GetOrCreateLocal(LB_RESULT, methodGenInfo.ReturnType);

            readAction(propertyField, il);
            il.EmitStoreLocal(resultB);

            this.EmitProcessParameters(codeGenerationInfo, propertyModel.GetterMethod, false, publicCompositeGenInfo, thisGenerationInfo, methodGenInfo);
            this.EmitProcessResult(codeGenerationInfo, propertyModel.GetterMethod, publicCompositeGenInfo, thisGenerationInfo, methodGenInfo);

            this.EmitThrowIfViolations(thisGenerationInfo, methodGenInfo, propertyModel.GetterMethod);

            il.EmitLoadLocal(resultB)
            .EmitReturn();
        }
Exemplo n.º 6
0
        protected virtual void EmitStoreExceptionListWithinCatch(
            CompositeMethodGenerationInfo methodGenInfo
            )
        {
            var il         = methodGenInfo.IL;
            var exceptionB = methodGenInfo.GetOrCreateLocal(LB_EXCEPTION);

            il.EmitStoreLocal(exceptionB);

            var exceptionListB    = methodGenInfo.GetOrCreateLocal(LB_EXCEPTION_LIST);
            var exceptionsOKLabel = il.DefineLabel();

            il
            .EmitLoadLocal(exceptionListB)
            .EmitBranch(BranchType.IF_TRUE, exceptionsOKLabel)
            .EmitNewObject(EXCEPTION_LIST_CTOR)
            .EmitStoreLocal(exceptionListB)
            .MarkLabel(exceptionsOKLabel)
            .EmitLoadLocal(exceptionListB)
            .EmitLoadLocal(exceptionB)
            .EmitCall(ADD_LAST_METHOD.ChangeDeclaringType(((CILType)exceptionListB.LocalType).GenericArguments.ToArray()));
        }
Exemplo n.º 7
0
 protected virtual void EmitEventInvocationWithTryCatchIfNeeded(
     EventInvocation invocationStyle,
     Type exceptionType,
     CompositeMethodGenerationInfo invokeMethod,
     CILMethod eventMethodToInvoke,
     Action <MethodIL> loadEventAction,
     Boolean storeResult
     )
 {
     invokeMethod.IL.EmitTryCatch(
         EXCEPTION_TYPE,
         il2 =>
     {
         loadEventAction(il2);
         for (Int32 idx = 0; idx < invokeMethod.Parameters.Count; ++idx)
         {
             il2.EmitLoadArg(invokeMethod.Parameters[idx].Position + 1);
         }
         il2.EmitCall(eventMethodToInvoke);
         if (storeResult && !VOID_TYPE.Equals(eventMethodToInvoke.GetReturnType()))
         {
             var resultB = invokeMethod.GetOrCreateLocal(LB_RESULT, invokeMethod.ReturnType);
             il2.EmitStoreLocal(resultB);
         }
     },
         EventInvocation.INVOKE_DIRECTLY.Equals(invocationStyle) ? (Action <MethodIL>)null : il2 =>
     {
         if (exceptionType != null)
         {
             this.EmitStoreExceptionListWithinCatch(invokeMethod);
         }
         else
         {
             throw new InternalException("Non-direct event invocation style, but no exception type specified.");
         }
     },
         false
         );
 }
 public void RegisterCompositeMethodGenerationInfo(CompositeMethodModel model, CompositeMethodGenerationInfo info)
 {
     this._compositeMethodGenerationInfos.TryAdd(model, info);
 }
        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 + ".");
                }
            }
        }
Exemplo n.º 10
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();
        }
Exemplo n.º 11
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 + ".");
                }
            }
        }
Exemplo n.º 12
0
        //protected virtual void EmitEventCheckMethodForWeaklyReferencedEvents(
        //   CILField eventField,
        //   MethodIL il
        //   )
        //{
        //   il.EmitLoadThisField( eventField )
        //     .EmitCall( WEAK_EVENT_ARRAY_CLEANUP_METHOD )
        //     .EmitLoadNull()
        //     .EmitCeq()
        //     .EmitLoadInt32( 0 )
        //     .EmitCeq()
        //     .EmitReturn();
        //}

        protected virtual void EmitEventInvocationMethodForStronglyReferencedEvents(
            EventModel eventModel,
            CompositeTypeGenerationInfo thisGenerationInfo,
            CILField eventField,
            CILTypeBase eventType,
            CompositeMethodGenerationInfo invokeMethod,
            CILMethod eventMethodToInvoke
            )
        {
            this.EmitEventInvocationMethodCore(
                eventModel,
                thisGenerationInfo,
                eventField,
                eventType,
                invokeMethod,
                eventMethodToInvoke,
                (eventLB, invocationStyle, exceptionType) =>
            {
                if (EventInvocation.INVOKE_DIRECTLY.Equals(invocationStyle))
                {
                    // Invocation method:
                    // private <return-type> Event<idx>Invoke(<args>)
                    // {
                    //    <event-type> evt = this._event<idx>;
                    //    if (evt != null)
                    //    {
                    //       (return) this._event<idx>(<args>);
                    //    } else <if has return type other than void>
                    //    {
                    //       throw new InvalidOperationException("The event " + <event name> + " is not set.");
                    //    }
                    // }
                    this.EmitEventInvocationWithTryCatchIfNeeded(
                        invocationStyle,
                        exceptionType,
                        invokeMethod,
                        eventMethodToInvoke,
                        il => il.EmitLoadLocal(eventLB),
                        false
                        );
                }
                else
                {
                    var il = invokeMethod.IL;
                    //  foreach ( Delegate handler in evt.GetInvocationList() )
                    //  {
                    //    try
                    //    {
                    //       result = handler(<args>);
                    //    }
                    //    catch ( Exception exc )
                    //    {
                    //      if ( exceptions == null )
                    //      {
                    //         exceptions = new LinkedList<Exception>();
                    //      }
                    //      exceptions.AddLast( exc );
                    //    }
                    //  }
                    var handlersB = invokeMethod.GetOrCreateLocal(LB_EVENT_HANDLERS);
                    il
                    .EmitLoadLocal(eventLB)
                    .EmitCall(GET_INVOCATION_LIST_METHOD)
                    .EmitStoreLocal(handlersB)

                    .EmitSimpleForLoop(
                        il2 =>
                    {
                        // Int32 index = 0;
                        var idxB = invokeMethod.GetOrCreateLocal(LB_INDEX);
                        il2
                        .EmitLoadInt32(0)
                        .EmitStoreLocal(idxB);
                        return(idxB);
                    },
                        (il2, idxB, loopBodyStartLabel) =>
                    {
                        // index < list.Length
                        il2
                        .EmitLoadLocal(idxB)
                        .EmitLoadLocal(handlersB)
                        .EmitLoadArrayLength()
                        .EmitNumericConversion(CILTypeCode.UInt32, CILTypeCode.Int32, false)
                        .EmitBranch(BranchType.IF_FIRST_LESSER_THAN_SECOND, loopBodyStartLabel);
                    },
                        E_MethodIL.EmitLeftPlusPlus,
                        (il2, idxB) =>
                    {
                        this.EmitEventInvocationWithTryCatchIfNeeded(
                            invocationStyle,
                            exceptionType,
                            invokeMethod,
                            eventMethodToInvoke,
                            il3 =>
                        {
                            il3
                            .EmitLoadLocal(handlersB)
                            .EmitLoadLocal(idxB)
                            .EmitLoadElement(handlersB.LocalType)
                            .EmitCastToType(handlersB.LocalType.GetElementType(), eventType);
                        },
                            true
                            );
                    }
                        );
                }
            });
        }
        protected override void EmitAfterCompositeMethodBodyBegan(
            IEnumerable <FragmentTypeGenerationInfo> fragmentTypeGenerationInfos,
            CompositeTypeGenerationInfo thisGenerationInfo,
            CompositeMethodGenerationInfo thisMethodGenerationInfo,
            SPI.Model.CompositeMethodModel compositeMethodModel
            )
        {
            var instanceableModel = compositeMethodModel.CompositeModel;

            // Need to emit code related to activation
            var il         = thisMethodGenerationInfo.IL;
            var cInstanceB = thisMethodGenerationInfo.GetLocalOrThrow(LB_C_INSTANCE);

            LocalBuilder compositeMethodModelB     = null;
            Boolean      hasOnInvocationInjections = this.HasOnInvocationInjections(compositeMethodModel.CompositeModel.SpecialMethods.Where(sMethod => sMethod.AllAttributes.OfType <ActivateAttribute>().Any() || sMethod.AllAttributes.OfType <PrototypeAttribute>().Any()));

            if (hasOnInvocationInjections)
            {
                this.InitializeComplexMethodModelLocalIfNecessary(compositeMethodModel, thisMethodGenerationInfo, out compositeMethodModelB);
            }

            // cInstance.ActivateIfNeeded(<method-index>, <gargs-info>, <next fragment>);
            il.EmitLoadLocal(cInstanceB)
            .EmitLoadInt32(compositeMethodModel.MethodIndex);
            if (thisMethodGenerationInfo.Builder.GenericArguments.Count > 0)
            {
                // new MethodGenericArgumentsInfo(<method-handle>, <type-handle>)
                var cMethodInfo = thisMethodGenerationInfo.OverriddenMethod.MakeGenericMethod(thisMethodGenerationInfo.GenericArguments.ToArray());
                il.Add(new OpCodeInfoWithMethodToken(
                           OpCodes.Ldtoken,
                           cMethodInfo))
                .Add(new OpCodeInfoWithTypeToken(
                         OpCodes.Ldtoken,
                         cMethodInfo.DeclaringType
                         ));
                il.EmitNewObject(this.METHOD_GENERIC_ARGUMENTS_INFO_CTOR);
            }
            else
            {
                il.EmitLoadNull();
            }

            if (hasOnInvocationInjections)
            {
                il.EmitLoadLocal(compositeMethodModelB);
                if (compositeMethodModel.Concerns.Any())
                {
                    il.EmitCall(CONCERN_MODELS_GETTER)
                    .EmitLoadInt32(0)
                    .EmitCall(CONCERN_MODELS_INDEXER);
                }
                else
                {
                    il.EmitCall(MIXIN_MODEL_GETTER);
                }
            }
            else
            {
                il.EmitLoadNull();
            }
            il.EmitCall(SERVICE_COMPOSITE_ACTIVATE_IF_NEEDED_METHOD);
        }