public LocaVariableCollectionTreeNode( MethodBodyDeclaration body ) : base( TreeViewImage.Folder, null ) { this.body = body; this.Text = "Locals"; this.EnableLatePopulate(); }
public LocaVariableCollectionTreeNode(MethodBodyDeclaration body) : base(TreeViewImage.Folder, null) { this.body = body; this.Text = "Locals"; this.EnableLatePopulate(); }
private static bool CheckIfIsLocationBinding(MethodBodyDeclaration methodBody, TransformationAssets assets) { bool isLocationBinding = methodBody.Method.Name == "SetValue" && methodBody.Method.DeclaringType.IsDerivedFrom(assets.LocationBindingTypeSignature.GetTypeDefinition()); return isLocationBinding; }
public override void Implement(TransformationContext context) { TypeDefDeclaration typeDef = (TypeDefDeclaration)context.TargetElement; ModuleDeclaration module = this.AspectWeaver.Module; ITypeSignature baseEntityType = module.Cache.GetType(typeof(BaseEntity)); // Find the base method. IMethod baseCopyToMethod = null; IType baseTypeCursor = typeDef; MethodSignature methodSignature = new MethodSignature(module, CallingConvention.HasThis, module.Cache.GetIntrinsic(IntrinsicType.Void), new[] { baseEntityType }, 0); while (baseCopyToMethod == null && baseTypeCursor != null) { TypeDefDeclaration baseTypeCursorTypeDef = baseTypeCursor.GetTypeDefinition(); baseCopyToMethod = baseTypeCursorTypeDef.Methods.GetMethod("CopyTo", methodSignature.Translate(baseTypeCursorTypeDef.Module), BindingOptions.OnlyExisting | BindingOptions.DontThrowException); baseTypeCursor = baseTypeCursorTypeDef.BaseType; } if (baseCopyToMethod == null) { throw new AssertionFailedException("Could not find a method CopyTo."); } if (baseCopyToMethod.DeclaringType == typeDef) { return; } // Declare the method. MethodDefDeclaration methodDef = new MethodDefDeclaration { Name = "CopyTo", Attributes = (MethodAttributes.Family | MethodAttributes.ReuseSlot | MethodAttributes.Virtual), CallingConvention = CallingConvention.HasThis }; typeDef.Methods.Add(methodDef); methodDef.CustomAttributes.Add(this.AspectWeaver.AspectInfrastructureTask.WeavingHelper.GetDebuggerNonUserCodeAttribute()); // Define parameter. methodDef.ReturnParameter = new ParameterDeclaration { ParameterType = module.Cache.GetIntrinsic(IntrinsicType.Void), Attributes = ParameterAttributes.Retval }; ParameterDeclaration cloneParameter = new ParameterDeclaration(0, "clone", baseEntityType); methodDef.Parameters.Add(cloneParameter); // Define the body MethodBodyDeclaration methodBody = new MethodBodyDeclaration(); methodDef.MethodBody = methodBody; InstructionBlock instructionBlock = methodBody.CreateInstructionBlock(); methodBody.RootInstructionBlock = instructionBlock; InstructionSequence sequence = methodBody.CreateInstructionSequence(); instructionBlock.AddInstructionSequence(sequence, NodePosition.After, null); using (InstructionWriter writer = new InstructionWriter()) { writer.AttachInstructionSequence(sequence); // Cast the argument and store it in a local variable. IType typeSpec = GenericHelper.GetTypeCanonicalGenericInstance(typeDef); LocalVariableSymbol castedCloneLocal = instructionBlock.DefineLocalVariable(typeSpec, "typedClone"); writer.EmitInstruction(OpCodeNumber.Ldarg_1); writer.EmitInstructionType(OpCodeNumber.Castclass, typeSpec); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, castedCloneLocal); // TODO: support generic base types. // Call the base method. writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstruction(OpCodeNumber.Ldarg_1); writer.EmitInstructionMethod(OpCodeNumber.Call, (IMethod)baseCopyToMethod.Translate(typeDef.Module)); // Loop on all fields and clone cloneable ones. TypeRefDeclaration cloneableTypeRef = (TypeRefDeclaration) module.Cache.GetType(typeof(ICloneable)); MethodRefDeclaration cloneMethodRef = (MethodRefDeclaration)cloneableTypeRef.MethodRefs.GetMethod( "Clone", new MethodSignature( module, CallingConvention.HasThis, module.Cache.GetIntrinsic( IntrinsicType.Object), new ITypeSignature[0], 0), BindingOptions.Default); foreach (FieldDefDeclaration fieldDef in typeDef.Fields) { if ((fieldDef.Attributes & FieldAttributes.Static) != 0) { continue; } if (fieldDef.FieldType == module.Cache.GetIntrinsic(IntrinsicType.String)) { continue; } // Does not work? //bool cloneable = fieldDef.FieldType.Inherits(cloneableTypeRef, GenericMap.Empty); bool cloneable = typeof(ICloneable).IsAssignableFrom(fieldDef.FieldType.GetSystemType(null, null)); if (cloneable) { IField fieldSpec = GenericHelper.GetFieldCanonicalGenericInstance(fieldDef); bool isValueType = fieldSpec.FieldType.BelongsToClassification(TypeClassifications.ValueType).Equals( NullableBool.True); InstructionSequence nextSequence = null; if (!isValueType) { nextSequence = methodBody.CreateInstructionSequence(); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionField(OpCodeNumber.Ldfld, fieldSpec); writer.EmitBranchingInstruction(OpCodeNumber.Brfalse, nextSequence); } writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, castedCloneLocal); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionField(OpCodeNumber.Ldfld, fieldSpec); if (isValueType) { writer.EmitInstructionType(OpCodeNumber.Box, fieldSpec.FieldType); } //writer.EmitInstructionType(OpCodeNumber.Castclass, cloneableTypeRef); writer.EmitInstructionMethod(OpCodeNumber.Callvirt, cloneMethodRef); if (isValueType) { writer.EmitInstructionType(OpCodeNumber.Unbox, fieldSpec.FieldType); writer.EmitInstructionType(OpCodeNumber.Ldobj, fieldSpec.FieldType); } else { writer.EmitInstructionType(OpCodeNumber.Castclass, fieldSpec.FieldType); } writer.EmitInstructionField(OpCodeNumber.Stfld, fieldSpec); if (!isValueType) { writer.DetachInstructionSequence(); instructionBlock.AddInstructionSequence(nextSequence, NodePosition.After, sequence); sequence = nextSequence; writer.AttachInstructionSequence(sequence); } } } writer.EmitInstruction(OpCodeNumber.Ret); writer.DetachInstructionSequence(); } }
private static void ImplementSetter( PropertyDeclaration property, TypeDefDeclaration type, IField field, MethodAttributes methodAttributes, CustomAttributeDeclaration compilerGenerated) { // Implement setter var setter = new MethodDefDeclaration { Attributes = methodAttributes, Name = "set_" + property.Name, CallingConvention = CallingConvention.HasThis, }; type.Methods.Add(setter); MarkCompilerGenerated(setter, compilerGenerated); setter.ReturnParameter = new ParameterDeclaration { ParameterType = type.Module.Cache.GetIntrinsic(IntrinsicType.Void), Attributes = ParameterAttributes.Retval }; setter.Parameters.Add(new ParameterDeclaration(0, "value", property.PropertyType)); var methodBody = new MethodBodyDeclaration(); var sequence = methodBody.CreateInstructionSequence(); var instructionBlock = methodBody.CreateInstructionBlock(); instructionBlock.AddInstructionSequence(sequence, NodePosition.After, null); methodBody.RootInstructionBlock = instructionBlock; setter.MethodBody = methodBody; var writer = new InstructionWriter(); writer.AttachInstructionSequence(sequence); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstruction(OpCodeNumber.Ldarg_1); writer.EmitInstructionField(OpCodeNumber.Stfld, field); writer.EmitInstruction(OpCodeNumber.Ret); writer.DetachInstructionSequence(); property.Members.Add(new MethodSemanticDeclaration(MethodSemantics.Setter, setter)); }
public static void ImplementRemoveOn( this EventDeclaration theEvent, TypeDefDeclaration type, IField field, WeavingHelper weavingHelper = null, MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot | MethodAttributes.SpecialName) { var module = type.Module; weavingHelper = weavingHelper ?? new WeavingHelper(module); var pEWeavingHelper = module.Cache.GetItem(() => new PostEdgeWeaverAssets(module)); var method = new MethodDefDeclaration { Attributes = methodAttributes, Name = "remove_" + theEvent.Name, CallingConvention = CallingConvention.HasThis }; type.Methods.Add(method); weavingHelper.AddCompilerGeneratedAttribute(method.CustomAttributes); var parameter = new ParameterDeclaration { Name = "value", ParameterType = theEvent.EventType, }; method.Parameters.Add(parameter); var methodBody = new MethodBodyDeclaration(); methodBody.EnsureWritableLocalVariables(); var instructionBlock = methodBody.CreateInstructionBlock(); var initSequence = methodBody.CreateInstructionSequence(); var loopSequence = methodBody.CreateInstructionSequence(); var endSequence = methodBody.CreateInstructionSequence(); instructionBlock.AddInstructionSequence(initSequence, NodePosition.After, null); instructionBlock.AddInstructionSequence(loopSequence, NodePosition.After, initSequence); instructionBlock.AddInstructionSequence(endSequence, NodePosition.After, loopSequence); methodBody.RootInstructionBlock = instructionBlock; method.MethodBody = methodBody; methodBody.CreateLocalVariable(theEvent.EventType); methodBody.CreateLocalVariable(theEvent.EventType); methodBody.CreateLocalVariable(theEvent.EventType); methodBody.CreateLocalVariable(module.Cache.GetIntrinsic(typeof(bool))); var writer = new InstructionWriter(); //Initialize writer.AttachInstructionSequence(initSequence); //PropertyChangedHandler handler = this.PropertyChanged writer.EmitInstruction(OpCodeNumber.Ldarg_0); //Get the this pointer writer.EmitInstructionField(OpCodeNumber.Ldfld, field); //Get the event's field writer.EmitInstruction(OpCodeNumber.Stloc_0); //store into the first local variable writer.DetachInstructionSequence(); //Loop //do { writer.AttachInstructionSequence(loopSequence); //PropertyChangedHandler handler2 = handler; writer.EmitInstruction(OpCodeNumber.Ldloc_0); writer.EmitInstruction(OpCodeNumber.Stloc_1); //PropertyChangedHandler handler3 = System.Delegate.Remove(handler2, value) writer.EmitInstruction(OpCodeNumber.Ldloc_1); writer.EmitInstruction(OpCodeNumber.Ldarg_1); writer.EmitInstructionMethod(OpCodeNumber.Call, pEWeavingHelper.DelegateRemoveMethod); writer.EmitInstructionType(OpCodeNumber.Castclass, theEvent.EventType); writer.EmitInstruction(OpCodeNumber.Stloc_2); //handler = System.Threading.Interlocked.CompareExchnage<PropertyChangedEventHandler>(ref this.PropertyChtyChanged, handler3, handler2); var compareExchangeMethodT = pEWeavingHelper.CompareExchangeMethod; var compareExchangeMethod = compareExchangeMethodT.GetGenericInstance(module, theEvent.EventType); writer.EmitInstruction(OpCodeNumber.Ldarg_0); //Load this writer.EmitInstructionField(OpCodeNumber.Ldflda, field); writer.EmitInstruction(OpCodeNumber.Ldloc_2); writer.EmitInstruction(OpCodeNumber.Ldloc_1); writer.EmitInstructionMethod(OpCodeNumber.Call, compareExchangeMethod); writer.EmitInstruction(OpCodeNumber.Stloc_0); //flag = handler != handler2; writer.EmitInstruction(OpCodeNumber.Ldloc_0); writer.EmitInstruction(OpCodeNumber.Ldloc_1); writer.EmitInstruction(OpCodeNumber.Ceq); writer.EmitInstruction(OpCodeNumber.Ldc_I4_0); writer.EmitInstruction(OpCodeNumber.Ceq); writer.EmitInstruction(OpCodeNumber.Stloc_3); //} while (flag); writer.EmitInstruction(OpCodeNumber.Ldloc_3); writer.EmitBranchingInstruction(OpCodeNumber.Brtrue_S, loopSequence); writer.DetachInstructionSequence(); //End writer.AttachInstructionSequence(endSequence); writer.EmitInstruction(OpCodeNumber.Ret); //Exit the method writer.DetachInstructionSequence(); theEvent.Members.Add(new MethodSemanticDeclaration(MethodSemantics.RemoveOn, method)); }
public override void Implement(TransformationContext context) { ModuleDeclaration module = this.AspectWeaver.Module; TypeDefDeclaration typeDef = (TypeDefDeclaration)context.TargetElement; // Declare the method. MethodDefDeclaration methodDef = new MethodDefDeclaration { Name = "AutoGeneratedValidate", Attributes = (MethodAttributes.Family | MethodAttributes.ReuseSlot | MethodAttributes.Virtual), CallingConvention = CallingConvention.HasThis }; typeDef.Methods.Add(methodDef); methodDef.CustomAttributes.Add(this.AspectWeaver.AspectInfrastructureTask.WeavingHelper.GetDebuggerNonUserCodeAttribute()); // Define parameter. methodDef.ReturnParameter = new ParameterDeclaration { ParameterType = module.Cache.GetIntrinsic(IntrinsicType.Void), Attributes = ParameterAttributes.Retval }; // Define the body MethodBodyDeclaration methodBody = new MethodBodyDeclaration(); methodDef.MethodBody = methodBody; InstructionBlock instructionBlock = methodBody.CreateInstructionBlock(); methodBody.RootInstructionBlock = instructionBlock; InstructionSequence sequence = methodBody.CreateInstructionSequence(); instructionBlock.AddInstructionSequence(sequence, NodePosition.After, null); using (InstructionWriter writer = new InstructionWriter()) { writer.AttachInstructionSequence( sequence ); // Find the base method. IMethod baseValidateMethod = null; IType baseTypeCursor = typeDef.BaseType; MethodSignature methodSignature = new MethodSignature( module, CallingConvention.HasThis, module.Cache.GetIntrinsic( IntrinsicType.Void ), new ITypeSignature[0], 0 ); while ( baseValidateMethod == null ) { TypeDefDeclaration baseTypeCursorTypeDef = baseTypeCursor.GetTypeDefinition(); baseValidateMethod = baseTypeCursorTypeDef.Methods.GetMethod( "AutoGeneratedValidate", methodSignature.Translate( baseTypeCursorTypeDef.Module ), BindingOptions.OnlyExisting | BindingOptions.DontThrowException ); baseTypeCursor = baseTypeCursorTypeDef.BaseType; } // TODO: support generic base types. // Call the base method. writer.EmitInstruction( OpCodeNumber.Ldarg_0 ); writer.EmitInstructionMethod( OpCodeNumber.Call, (IMethod) baseValidateMethod.Translate( typeDef.Module ) ); // Make an array with the boxed field values. TypeValidationAspect aspect = (TypeValidationAspect) this.AspectWeaverInstance.Aspect; LocalVariableSymbol fieldValuesArrayLocal = instructionBlock.DefineLocalVariable( module.Cache.GetType( typeof(object[]) ), "fieldValues" ); writer.EmitInstructionInt32( OpCodeNumber.Ldc_I4, aspect.Validators.Count ); writer.EmitInstructionType( OpCodeNumber.Newarr, module.Cache.GetIntrinsic( IntrinsicType.Object ) ); writer.EmitInstructionLocalVariable( OpCodeNumber.Stloc, fieldValuesArrayLocal ); int i = 0; foreach ( FieldValidationAttribute validator in aspect.Validators ) { FieldDefDeclaration fieldDef = typeDef.Fields.GetByName( validator.TargetLocation.Name ); IField fieldSpec = GenericHelper.GetFieldCanonicalGenericInstance( fieldDef ); writer.EmitInstructionLocalVariable( OpCodeNumber.Ldloc, fieldValuesArrayLocal ); writer.EmitInstructionInt32( OpCodeNumber.Ldc_I4, i ); writer.EmitInstruction( OpCodeNumber.Ldarg_0 ); writer.EmitInstructionField( OpCodeNumber.Ldfld, fieldSpec ); writer.EmitConvertToObject( fieldSpec.FieldType ); writer.EmitInstruction( OpCodeNumber.Stelem_Ref ); i++; } // Get the validator method. IMethod validateMethod = module.Cache.GetItem( () => module.FindMethod( typeof(TypeValidationAspect).GetMethod( "Validate" ), BindingOptions.Default ) ); // Call the validator. this.AspectWeaverInstance.AspectRuntimeInstanceField.EmitLoadField( writer, null ); writer.EmitInstructionLocalVariable( OpCodeNumber.Ldloc, fieldValuesArrayLocal ); writer.EmitInstructionMethod( OpCodeNumber.Callvirt, validateMethod ); writer.EmitInstruction( OpCodeNumber.Ret ); writer.DetachInstructionSequence(); } }
public override void Implement( TransformationContext context ) { TypeDefDeclaration typeDef = (TypeDefDeclaration) context.TargetElement; ModuleDeclaration module = this.AspectWeaver.Module; ITypeSignature baseEntityType = module.Cache.GetType( typeof(BaseEntity) ); // Find the base method. IMethod baseCopyToMethod = null; IType baseTypeCursor = typeDef; MethodSignature methodSignature = new MethodSignature(module, CallingConvention.HasThis, module.Cache.GetIntrinsic(IntrinsicType.Void), new[] { baseEntityType }, 0); while (baseCopyToMethod == null && baseTypeCursor != null) { TypeDefDeclaration baseTypeCursorTypeDef = baseTypeCursor.GetTypeDefinition(); baseCopyToMethod = baseTypeCursorTypeDef.Methods.GetMethod("CopyTo", methodSignature.Translate(baseTypeCursorTypeDef.Module), BindingOptions.OnlyExisting | BindingOptions.DontThrowException); baseTypeCursor = baseTypeCursorTypeDef.BaseType; } if (baseCopyToMethod == null) throw new AssertionFailedException("Could not find a method CopyTo."); if ( baseCopyToMethod.DeclaringType == typeDef ) return; // Declare the method. MethodDefDeclaration methodDef = new MethodDefDeclaration { Name = "CopyTo", Attributes = (MethodAttributes.Family | MethodAttributes.ReuseSlot | MethodAttributes.Virtual), CallingConvention = CallingConvention.HasThis }; typeDef.Methods.Add( methodDef ); methodDef.CustomAttributes.Add( this.AspectWeaver.AspectInfrastructureTask.WeavingHelper.GetDebuggerNonUserCodeAttribute() ); // Define parameter. methodDef.ReturnParameter = new ParameterDeclaration { ParameterType = module.Cache.GetIntrinsic( IntrinsicType.Void ), Attributes = ParameterAttributes.Retval }; ParameterDeclaration cloneParameter = new ParameterDeclaration( 0, "clone", baseEntityType ); methodDef.Parameters.Add( cloneParameter ); // Define the body MethodBodyDeclaration methodBody = new MethodBodyDeclaration(); methodDef.MethodBody = methodBody; InstructionBlock instructionBlock = methodBody.CreateInstructionBlock(); methodBody.RootInstructionBlock = instructionBlock; InstructionSequence sequence = methodBody.CreateInstructionSequence(); instructionBlock.AddInstructionSequence( sequence, NodePosition.After, null ); using (InstructionWriter writer = new InstructionWriter()) { writer.AttachInstructionSequence( sequence ); // Cast the argument and store it in a local variable. IType typeSpec = GenericHelper.GetTypeCanonicalGenericInstance( typeDef ); LocalVariableSymbol castedCloneLocal = instructionBlock.DefineLocalVariable( typeSpec, "typedClone" ); writer.EmitInstruction( OpCodeNumber.Ldarg_1 ); writer.EmitInstructionType( OpCodeNumber.Castclass, typeSpec ); writer.EmitInstructionLocalVariable( OpCodeNumber.Stloc, castedCloneLocal ); // TODO: support generic base types. // Call the base method. writer.EmitInstruction( OpCodeNumber.Ldarg_0 ); writer.EmitInstruction( OpCodeNumber.Ldarg_1 ); writer.EmitInstructionMethod( OpCodeNumber.Call, (IMethod) baseCopyToMethod.Translate( typeDef.Module ) ); // Loop on all fields and clone cloneable ones. TypeRefDeclaration cloneableTypeRef = (TypeRefDeclaration) module.Cache.GetType( typeof(ICloneable) ); MethodRefDeclaration cloneMethodRef = (MethodRefDeclaration) cloneableTypeRef.MethodRefs.GetMethod( "Clone", new MethodSignature( module, CallingConvention.HasThis, module.Cache.GetIntrinsic( IntrinsicType.Object ), new ITypeSignature[0], 0 ), BindingOptions.Default ); foreach ( FieldDefDeclaration fieldDef in typeDef.Fields ) { if ( (fieldDef.Attributes & FieldAttributes.Static) != 0 ) continue; if ( fieldDef.FieldType == module.Cache.GetIntrinsic( IntrinsicType.String ) ) continue; // Does not work? //bool cloneable = fieldDef.FieldType.Inherits(cloneableTypeRef, GenericMap.Empty); bool cloneable = typeof(ICloneable).IsAssignableFrom( fieldDef.FieldType.GetSystemType( null, null ) ); if ( cloneable ) { IField fieldSpec = GenericHelper.GetFieldCanonicalGenericInstance( fieldDef ); bool isValueType = fieldSpec.FieldType.BelongsToClassification( TypeClassifications.ValueType ).Equals( NullableBool.True ); InstructionSequence nextSequence = null; if ( !isValueType ) { nextSequence = methodBody.CreateInstructionSequence(); writer.EmitInstruction( OpCodeNumber.Ldarg_0 ); writer.EmitInstructionField( OpCodeNumber.Ldfld, fieldSpec ); writer.EmitBranchingInstruction( OpCodeNumber.Brfalse, nextSequence ); } writer.EmitInstructionLocalVariable( OpCodeNumber.Ldloc, castedCloneLocal ); writer.EmitInstruction( OpCodeNumber.Ldarg_0 ); writer.EmitInstructionField( OpCodeNumber.Ldfld, fieldSpec ); if ( isValueType ) { writer.EmitInstructionType( OpCodeNumber.Box, fieldSpec.FieldType ); } //writer.EmitInstructionType(OpCodeNumber.Castclass, cloneableTypeRef); writer.EmitInstructionMethod( OpCodeNumber.Callvirt, cloneMethodRef ); if ( isValueType ) { writer.EmitInstructionType( OpCodeNumber.Unbox, fieldSpec.FieldType ); writer.EmitInstructionType( OpCodeNumber.Ldobj, fieldSpec.FieldType ); } else { writer.EmitInstructionType( OpCodeNumber.Castclass, fieldSpec.FieldType ); } writer.EmitInstructionField( OpCodeNumber.Stfld, fieldSpec ); if ( !isValueType ) { writer.DetachInstructionSequence(); instructionBlock.AddInstructionSequence( nextSequence, NodePosition.After, sequence ); sequence = nextSequence; writer.AttachInstructionSequence( sequence ); } } } writer.EmitInstruction( OpCodeNumber.Ret ); writer.DetachInstructionSequence(); } }
public override void Implement(TransformationContext context) { ModuleDeclaration module = this.AspectWeaver.Module; TypeDefDeclaration typeDef = (TypeDefDeclaration)context.TargetElement; // Declare the method. MethodDefDeclaration methodDef = new MethodDefDeclaration { Name = "AutoGeneratedValidate", Attributes = (MethodAttributes.Family | MethodAttributes.ReuseSlot | MethodAttributes.Virtual), CallingConvention = CallingConvention.HasThis }; typeDef.Methods.Add(methodDef); methodDef.CustomAttributes.Add(this.AspectWeaver.AspectInfrastructureTask.WeavingHelper.GetDebuggerNonUserCodeAttribute()); // Define parameter. methodDef.ReturnParameter = new ParameterDeclaration { ParameterType = module.Cache.GetIntrinsic(IntrinsicType.Void), Attributes = ParameterAttributes.Retval }; // Define the body MethodBodyDeclaration methodBody = new MethodBodyDeclaration(); methodDef.MethodBody = methodBody; InstructionBlock instructionBlock = methodBody.CreateInstructionBlock(); methodBody.RootInstructionBlock = instructionBlock; InstructionSequence sequence = methodBody.CreateInstructionSequence(); instructionBlock.AddInstructionSequence(sequence, NodePosition.After, null); using (InstructionWriter writer = new InstructionWriter()) { writer.AttachInstructionSequence(sequence); // Find the base method. IMethod baseValidateMethod = null; IType baseTypeCursor = typeDef.BaseType; MethodSignature methodSignature = new MethodSignature(module, CallingConvention.HasThis, module.Cache.GetIntrinsic(IntrinsicType.Void), new ITypeSignature[0], 0); while (baseValidateMethod == null) { TypeDefDeclaration baseTypeCursorTypeDef = baseTypeCursor.GetTypeDefinition(); baseValidateMethod = baseTypeCursorTypeDef.Methods.GetMethod("AutoGeneratedValidate", methodSignature.Translate(baseTypeCursorTypeDef.Module), BindingOptions.OnlyExisting | BindingOptions.DontThrowException); baseTypeCursor = baseTypeCursorTypeDef.BaseType; } // TODO: support generic base types. // Call the base method. writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionMethod(OpCodeNumber.Call, (IMethod)baseValidateMethod.Translate(typeDef.Module)); // Make an array with the boxed field values. TypeValidationAspect aspect = (TypeValidationAspect)this.AspectWeaverInstance.Aspect; LocalVariableSymbol fieldValuesArrayLocal = instructionBlock.DefineLocalVariable( module.Cache.GetType(typeof(object[])), "fieldValues"); writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, aspect.Validators.Count); writer.EmitInstructionType(OpCodeNumber.Newarr, module.Cache.GetIntrinsic(IntrinsicType.Object)); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, fieldValuesArrayLocal); int i = 0; foreach (FieldValidationAttribute validator in aspect.Validators) { FieldDefDeclaration fieldDef = typeDef.Fields.GetByName(validator.TargetLocation.Name); IField fieldSpec = GenericHelper.GetFieldCanonicalGenericInstance(fieldDef); writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, fieldValuesArrayLocal); writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, i); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionField(OpCodeNumber.Ldfld, fieldSpec); writer.EmitConvertToObject(fieldSpec.FieldType); writer.EmitInstruction(OpCodeNumber.Stelem_Ref); i++; } // Get the validator method. IMethod validateMethod = module.Cache.GetItem( () => module.FindMethod( typeof(TypeValidationAspect).GetMethod("Validate"), BindingOptions.Default)); // Call the validator. this.AspectWeaverInstance.AspectRuntimeInstanceField.EmitLoadField(writer, null); writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, fieldValuesArrayLocal); writer.EmitInstructionMethod(OpCodeNumber.Callvirt, validateMethod); writer.EmitInstruction(OpCodeNumber.Ret); writer.DetachInstructionSequence(); } }