예제 #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);
     })
         );
 }
        protected virtual void EmitCheckPropertyImmutability(
            PropertyModel propertyModel,
            CompositeTypeGenerationInfo thisGenerationInfo,
            MethodIL il
            )
        {
            if (propertyModel.IsImmutable)
            {
                var setPropertyLabelWrapper = il.DefineLabel();
                il
                .EmitLoadThisField(thisGenerationInfo.CompositeField)
                .EmitCall(IS_PROTOTYPE_GETTER)
                .EmitBranch(BranchType.IF_TRUE, setPropertyLabelWrapper)

                .EmitLoadString("Can not set immutable property ")
                .EmitReflectionObjectOf(thisGenerationInfo.Parents[propertyModel.NativeInfo.DeclaringType.NewWrapperAsType(this.ctx)])
                .EmitLoadString(propertyModel.NativeInfo.Name)
                .EmitCall(QNAME_FROM_TYPE_AND_NAME)
                .EmitCall(TO_STRING_METHOD)
                .EmitLoadString("for a non-prototype composite instance.")
                .EmitCall(STRING_CONCAT_METHOD_3)
                .EmitThrowNewException(INVALID_OPERATION_EXCEPTION_CTOR_WITH_STRING)

                .MarkLabel(setPropertyLabelWrapper);
            }
        }
예제 #3
0
 protected virtual Boolean IsCompositeGeneratedEvent(
     CompositeTypeGenerationInfo thisGenerationInfo,
     EventModel eventModel,
     Type genericEventMixinType
     )
 {
     return(!thisGenerationInfo.AutoGeneratedEventInfos.ContainsKey(eventModel.NativeInfo) &&
            eventModel.AddMethod != null &&
            eventModel.RemoveMethod != null &&
            genericEventMixinType.Equals(eventModel.AddMethod.Mixin.NativeInfo.DeclaringType) &&
            genericEventMixinType.Equals(eventModel.RemoveMethod.Mixin.NativeInfo.DeclaringType));
 }
예제 #4
0
 protected override void EmitPublicCompositeHashCode(
     CompositeCodeGenerationInfo codeGenerationInfo,
     CompositeModel compositeModel,
     CompositeTypeModel typeModel,
     CompositeTypeGenerationInfo publicCompositeGenInfo,
     CompositeTypeGenerationInfo thisGenInfo,
     CompositeEmittingInfo emittingInfo,
     IEnumerable <FragmentTypeGenerationInfo> fragmentGenerationInfos
     )
 {
     this.EmitPlainCompositeHashCode(codeGenerationInfo, compositeModel, typeModel, publicCompositeGenInfo, thisGenInfo, emittingInfo, fragmentGenerationInfos);
 }
 protected virtual Boolean IsCompositeGeneratedProperty(
     CompositeTypeGenerationInfo thisGenerationInfo,
     PropertyModel propertyModel,
     Type genericPropertyMixinType
     )
 {
     return(!thisGenerationInfo.AutoGeneratedPropertyInfos.ContainsKey(propertyModel.NativeInfo) &&
            propertyModel.GetterMethod != null &&
            propertyModel.SetterMethod != null &&
            genericPropertyMixinType.Equals(propertyModel.GetterMethod.Mixin.NativeInfo.DeclaringType) &&
            genericPropertyMixinType.Equals(propertyModel.SetterMethod.Mixin.NativeInfo.DeclaringType));
 }
        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 override void EmitTheRestOfPublicCompositeConstructor(
            CompositeCodeGenerationInfo codeGenerationInfo,
            CompositeModel model,
            CompositeTypeModel typeModel,
            CompositeEmittingInfo emittingInfo,
            IEnumerable <FragmentTypeGenerationInfo> fragmentGenerationInfos,
            CompositeTypeGenerationInfo thisGenerationInfo,
            ConstructorGenerationInfo ctorGenerationInfo,
            Int32 firstAdditionalParameterIndex
            )
        {
            base.EmitTheRestOfPublicCompositeConstructor(codeGenerationInfo, model, typeModel, emittingInfo, fragmentGenerationInfos, thisGenerationInfo, ctorGenerationInfo, firstAdditionalParameterIndex);

            Int32 baseAdditionalParamsCount = base.GetAmountOfAdditionalArgumentsForPublicCompositeConstructor();

            this.EmitSetActionMethod <ActivateAttribute>(
                codeGenerationInfo,
                model,
                typeModel,
                fragmentGenerationInfos,
                thisGenerationInfo,
                thisGenerationInfo,
                emittingInfo,
                ctorGenerationInfo,
                firstAdditionalParameterIndex + baseAdditionalParamsCount,
                ACTIVATION_METHOD_NAME,
                false
                );

            this.EmitSetActionMethod <PassivateAttribute>(
                codeGenerationInfo,
                model,
                typeModel,
                fragmentGenerationInfos,
                thisGenerationInfo,
                thisGenerationInfo,
                emittingInfo,
                ctorGenerationInfo,
                firstAdditionalParameterIndex + baseAdditionalParamsCount + 1,
                PASSIVATION_METHOD_NAME,
                true
                );
        }
        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();
        }
예제 #11
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 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);
        }
예제 #13
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
                            );
                    }
                        );
                }
            });
        }
예제 #14
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 + ".");
                }
            }
        }
        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() + ".");
                }
            }
        }
 public Boolean IsMainCompositeGenerationInfo(CompositeTypeGenerationInfo typeGenInfo, CILType mainCompositeTypeAttributeType)
 {
     return(typeGenInfo.Builder.CustomAttributeData.Any(d => d.Constructor.DeclaringType.Equals(mainCompositeTypeAttributeType)));
 }
 public void AddPublicCompositeGenerationInfo(Assembly assembly, CompositeModel compositeModel, CompositeTypeGenerationInfo typeGenInfo)
 {
     this._publicCompositeGenerationInfo.TryAdd(Tuple.Create(assembly, compositeModel), typeGenInfo);
     //Interlocked.CompareExchange( ref this._firstPublicTypeGenInfo, typeGenInfo, null );
 }
예제 #18
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();
        }
 public Boolean IsMainCompositeGenerationInfo(CompositeTypeGenerationInfo typeGenInfo, Assembly assemblyBeingProcessed)
 {
     return(typeGenInfo.CompositeModel.MainCodeGenerationType.Assembly.Equals(assemblyBeingProcessed));
     //return Object.ReferenceEquals( this._firstPublicTypeGenInfo, typeGenInfo );
 }
        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 + ".");
                }
            }
        }
 public Boolean TryAddTypeWithCompositeMethods(CompositeTypeGenerationInfo type)
 {
     return(this._typesWithCompositeMethods.TryAdd(type, type));
 }
 protected override IEnumerable <CILType> GetPublicCompositeAdditionalArguments(CompositeTypeGenerationInfo typeGenInfo)
 {
     return(base.GetPublicCompositeAdditionalArguments(typeGenInfo).Concat(ACTION_REF_TYPES_2));
 }