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); } }
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(); }