protected internal override void OnPopulate(TreeViewCancelEventArgs e) { TypeRefDeclaration externalType = this.Declaration as TypeRefDeclaration; if (externalType.TypeRefs.Count > 0) { this.Nodes.Add(new ExternalTypeFolderTreeNode(externalType, "Nested Types")); } ExternalFieldTreeNode.PopulateExternalMembers(externalType, this.Nodes, false); }
public ExternalTypeTreeNode( TypeRefDeclaration externalType ) : base( externalType, TreeViewImage.Class, TreeViewImage.Reference ) { this.Text = externalType.Name; 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(); } }
public ExternalTypeTreeNode(TypeRefDeclaration externalType) : base(externalType, TreeViewImage.Class, TreeViewImage.Reference) { this.Text = externalType.Name; this.EnableLatePopulate(); }