示例#1
0
    private static void AddPropertyInitializeInterception(
        Builder builder,
        BuilderTypePropertyInterceptionInfo propertyInterceptionInfo,
        PropertyBuilderInfo member,
        Field propertyField,
        Method actionObjectCtor,
        Method propertySetter,
        Dictionary <string, Field> interceptorFields)
    {
        var declaringType         = member.Property.OriginType;
        var syncRoot              = BuilderTypes.ISyncRoot;
        var legalInitInterceptors = member.InterceptorInfos.Where(x => x.InterfaceInitializer != null).ToArray();
        var relevantCtors         = member.Property.IsStatic ? new Method[] { declaringType.StaticConstructor } : declaringType.GetRelevantConstructors().Where(x => x.Name != ".cctor");

        foreach (var ctor in relevantCtors)
        {
            ctor.NewCoder()
            .Context(context =>
            {
                for (int i = 0; i < legalInitInterceptors.Length; i++)
                {
                    var item  = legalInitInterceptors[i];
                    var field = interceptorFields[item.Attribute.Identification];

                    context.SetValue(field, x => x.NewObj(item.Attribute));

                    if (item.HasSyncRootInterface)
                    {
                        context.Load(field).As(BuilderTypes.ISyncRoot).Call(syncRoot.GetMethod_set_SyncRoot(), member.SyncRoot);
                    }

                    ModuleWeaver.ImplementAssignMethodAttribute(builder, legalInitInterceptors[i].AssignMethodAttributeInfos, field, item.Attribute.Attribute.Type, context);
                }

                context.SetValue(propertyField, x =>
                                 x.NewObj(propertyInterceptionInfo.GetMethod_ctor(),
                                          member.Property.Getter,
                                          member.Property.Setter,
                                          member.Property.Name,
                                          member.Property.ReturnType,
                                          CodeBlocks.This,
                                          member.Property.ReturnType.IsArray || member.Property.ReturnType.Implements(typeof(IEnumerable)) ? member.Property.ReturnType.ChildType : null,
                                          propertySetter == null ? null : x.NewCoder().NewObj(actionObjectCtor, propertySetter.ThisOrNull(), propertySetter)));

                for (int i = 0; i < legalInitInterceptors.Length; i++)
                {
                    var item  = legalInitInterceptors[i];
                    var field = interceptorFields[item.Attribute.Identification];
                    context.Load(field).As(item.InterfaceInitializer)
                    .Call(item.InterfaceInitializer.GetMethod_OnInitialize(), propertyField, member.Property.BackingField);
                }

                return(context);
            })
            .Insert(InsertionPosition.Beginning);
        }
    }
示例#2
0
    private static void CreatePropertySetterDelegate(Builder builder, PropertyBuilderInfo member, Method propertySetter)
    {
        // If we don't have a backing field and we don't have a setter and getter
        // don't bother creating a setter delegate
        if (member.Property.BackingField == null && propertySetter == null)
        {
            return;
        }

        if (member.Property.BackingField == null && member.Property.Getter != null && member.Property.Setter != null)
        {
            // The copies are used to access the property as fake backing fields to avoid
            // stack overflows by getter and setter calling each other until ethernity
            member.Property.Getter.Copy();
            member.Property.Setter.Copy();

            CreateSetterDelegate(builder, propertySetter, member.Property.ReturnType, member.Property);
        }
        else if (member.Property.BackingField != null && !member.Property.BackingField.FieldType.IsGenericType)
        {
            CreateSetterDelegate(builder, propertySetter, member.Property.BackingField.FieldType, member.Property.BackingField);
        }
        else if (member.Property.BackingField == null && member.Property.Setter != null)
        {
            var methodSetter = member.Property.Setter.Copy();
            propertySetter.NewCoder().Call(methodSetter, CodeBlocks.GetParameter(0)).Return().Replace();
        }
        else if (member.Property.BackingField == null && member.Property.Getter != null)
        {
            // This shouldn't be a thing
        }
        else
        {
            propertySetter.NewCoder().SetValue(member.Property.BackingField, CodeBlocks.GetParameter(0)).Return().Replace();
        }
    }
示例#3
0
    private static void AddPropertySetterInterception(
        Builder builder,
        BuilderTypePropertyInterceptionInfo propertyInterceptionInfo,
        PropertyBuilderInfo member,
        Field propertyField,
        Method actionObjectCtor,
        Method propertySetter,
        Dictionary <string, Field> interceptorFields)
    {
        var syncRoot = BuilderTypes.ISyncRoot;
        var legalSetterInterceptors = member.InterceptorInfos.Where(x => x.InterfaceSetter != null).ToArray();

        member.Property.Setter
        .NewCoder()
        .Context(context =>
        {
            if (member.HasInitializer)
            {
                return(context);
            }

            for (int i = 0; i < legalSetterInterceptors.Length; i++)
            {
                var item = legalSetterInterceptors[i];
                var alwaysCreateNewInstance = item.InterceptorInfo.AlwaysCreateNewInstance && item.InterfaceInitializer == null;
                var fieldOrVariable         = interceptorFields[item.Attribute.Identification] as CecilatorBase ??
                                              context.AssociatedMethod.GetOrCreateVariable(item.Attribute.Attribute.Type, item.Attribute.Identification);

                Coder implementInterceptorInitialization(Coder coder)
                {
                    coder.SetValue(fieldOrVariable, x => x.NewObj(item.Attribute));

                    if (item.HasSyncRootInterface)
                    {
                        coder.Load <ICasting>(fieldOrVariable).As(syncRoot.BuilderType.Import()).To <ICallMethod <CallCoder> >().Call(syncRoot.GetMethod_set_SyncRoot(), member.SyncRoot);
                    }

                    ModuleWeaver.ImplementAssignMethodAttribute(builder, legalSetterInterceptors[i].AssignMethodAttributeInfos, fieldOrVariable, item.Attribute.Attribute.Type, coder);

                    return(coder);
                }

                if (alwaysCreateNewInstance)
                {
                    implementInterceptorInitialization(context);
                }
                else
                {
                    context.If(x => x.Load <IRelationalOperators>(fieldOrVariable).IsNull(), then => implementInterceptorInitialization(then));
                }

                item.Attribute.Remove();
            }

            return(context.If(x => x.Load(propertyField).IsNull(), then =>
                              then.SetValue(propertyField, x =>
                                            x.NewObj(propertyInterceptionInfo.GetMethod_ctor(),
                                                     member.Property.Getter,
                                                     member.Property.Setter,
                                                     member.Property.Name,
                                                     member.Property.ReturnType,
                                                     CodeBlocks.This,
                                                     member.Property.ReturnType.IsArray || member.Property.ReturnType.Implements(typeof(IEnumerable)) ? member.Property.ReturnType.ChildType : null,
                                                     propertySetter == null ? null : x.NewCoder().NewObj(actionObjectCtor, propertySetter.ThisOrNull(), propertySetter)))));
        })
        .Try(@try =>
        {
            if (member.Property.BackingField == null)
            {
                // If we don't have a backing field, we will try getting the value from the
                // getter itself... But in this case we have to watch out that we don't accidentally code a
                // StackOverFlow
                var oldvalue = member.Property.Getter == null ? null : member.Property.Setter.GetOrCreateVariable(member.Property.ReturnType);

                if (oldvalue != null)
                {
                    var getter = member.Property.Getter.Copy();
                    @try.SetValue(oldvalue, y => y.Call(getter));
                }

                for (int i = 0; i < legalSetterInterceptors.Length; i++)
                {
                    var item = legalSetterInterceptors[i];
                    var alwaysCreateNewInstance = item.InterceptorInfo.AlwaysCreateNewInstance && item.InterfaceInitializer == null;
                    var fieldOrVariable         = interceptorFields[item.Attribute.Identification] as CecilatorBase ?? @try.AssociatedMethod.GetVariable(item.Attribute.Identification);
                    @try.If(x =>
                            x.Load <ICasting>(fieldOrVariable)
                            .As(legalSetterInterceptors[i].InterfaceSetter)
                            .To <ICallMethod <BooleanExpressionCallCoder> >()
                            .Call(item.InterfaceSetter.GetMethod_OnSet(), propertyField, oldvalue, CodeBlocks.GetParameter(0))
                            .To <IRelationalOperators>()
                            .Is(false), then => then.OriginalBody(true));
                }
            }
            else
            {
                @try.If(x => x.And(legalSetterInterceptors,
                                   (coder, item, i) =>
                {
                    var fieldOrVariable = interceptorFields[item.Attribute.Identification] as CecilatorBase ?? @try.AssociatedMethod.GetVariable(item.Attribute.Identification);
                    return(coder.Load <ICasting>(fieldOrVariable)
                           .As(legalSetterInterceptors[i].InterfaceSetter)
                           .To <ICallMethod <BooleanExpressionCallCoder> >()
                           .Call(item.InterfaceSetter.GetMethod_OnSet(), propertyField, member.Property.BackingField, CodeBlocks.GetParameter(0)));
                }).Is(false), then => then.OriginalBody());
            }

            return(@try);
        })
        .Catch(typeof(Exception), (ex, e) =>
        {
            return(ex.If(x => x.Or(legalSetterInterceptors,
                                   (coder, y, i) =>
            {
                var fieldOrVariable = interceptorFields[y.Attribute.Identification] as CecilatorBase ?? ex.AssociatedMethod.GetVariable(y.Attribute.Identification);
                return coder.Load <ICasting>(fieldOrVariable)
                .As(legalSetterInterceptors[i].InterfaceSetter)
                .To <ICallMethod <BooleanExpressionCallCoder> >()
                .Call(legalSetterInterceptors[i].InterfaceSetter.GetMethod_OnException(), e());
            }).Is(true), then => ex.NewCoder().Rethrow())
                   .DefaultValue()
                   .Return());
        })
        .Finally(x =>
        {
            for (int i = 0; i < legalSetterInterceptors.Length; i++)
            {
                var item            = legalSetterInterceptors[i];
                var fieldOrVariable = interceptorFields[item.Attribute.Identification] as CecilatorBase ?? x.AssociatedMethod.GetVariable(item.Attribute.Identification);
                x.Load <ICasting>(fieldOrVariable)
                .As(legalSetterInterceptors[i].InterfaceSetter)
                .To <ICallMethod <CallCoder> >()
                .Call(legalSetterInterceptors[i].InterfaceSetter.GetMethod_OnExit());
            }

            return(x);
        })
        .EndTry()
        .Return()
        .Replace();
    }