public ExternalMethodTreeNode(MethodRefDeclaration externalMethod, bool red) : base(externalMethod, TreeViewImage.Method, TreeViewImage.Reference) { this.method = externalMethod; StringBuilder name = new StringBuilder(255); name.Append(method.Name); bool first = true; if (method.Signature.ParameterTypes.Count > 0) { name.Append("("); for (int i = 0; i < method.Signature.ParameterTypes.Count; i++) { if (!first) { name.Append(", "); } else { name.Append(' '); first = false; } name.Append(method.Signature.ParameterTypes[i].ToString()); } name.Append(" )"); } name.Append(" : "); name.Append(method.Signature.ReturnType.ToString()); this.Text = name.ToString(); if (red) { this.ForeColor = Color.Red; } this.EnableLatePopulate(); }
public ExternalMethodTreeNode( MethodRefDeclaration externalMethod, bool red ) : base( externalMethod, TreeViewImage.Method, TreeViewImage.Reference ) { this.method = externalMethod; StringBuilder name = new StringBuilder( 255 ); name.Append( method.Name ); bool first = true; if ( method.Signature.ParameterTypes.Count > 0 ) { name.Append( "(" ); for ( int i = 0 ; i < method.Signature.ParameterTypes.Count ; i++ ) { if ( !first ) { name.Append( ", " ); } else { name.Append( ' ' ); first = false; } name.Append( method.Signature.ParameterTypes[i].ToString() ); } name.Append( " )" ); } name.Append( " : " ); name.Append( method.Signature.ReturnType.ToString() ); this.Text = name.ToString(); if ( red ) this.ForeColor = Color.Red; this.EnableLatePopulate(); }
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(); } }