/// <summary> /// /// </summary> /// <param name="writer"></param> /// <param name="type">the current type being extended</param> /// <param name="extensionMethodTemplate">A reference to the extension method. For generic methods, this is a reference to the /// non-specialized method, e.g. System.Linq.Enumerable.Select``2. /// </param> /// <param name="specialization">When the current type implements or inherits from a specialization of a generic type, /// this parameter has a TypeNode for the type used as apecialization of the generic type's first template param. /// </param> private void AddExtensionMethod(XmlWriter writer, TypeNode type, Method extensionMethodTemplate, TypeNode specialization) { // If this is a specialization of a generic method, construct a Method object that describes the specialization Method extensionMethodTemplate2 = extensionMethodTemplate; if (extensionMethodTemplate2.IsGeneric && (specialization != null)) { // the specialization type is the first of the method's template arguments TypeNodeList templateArgs = new TypeNodeList(); templateArgs.Add(specialization); // add any additional template arguments for (int i = 1; i < extensionMethodTemplate.TemplateParameters.Count; i++) templateArgs.Add(extensionMethodTemplate.TemplateParameters[i]); extensionMethodTemplate2 = extensionMethodTemplate.GetTemplateInstance(type, templateArgs); } TypeNode extensionMethodTemplateReturnType = extensionMethodTemplate2.ReturnType; ParameterList extensionMethodTemplateParameters = extensionMethodTemplate2.Parameters; ParameterList extensionMethodParameters = new ParameterList(); for (int i = 1; i < extensionMethodTemplateParameters.Count; i++) { Parameter extensionMethodParameter = extensionMethodTemplateParameters[i]; extensionMethodParameters.Add(extensionMethodParameter); } Method extensionMethod = new Method(extensionMethodTemplate.DeclaringType, new AttributeList(), extensionMethodTemplate.Name, extensionMethodParameters, extensionMethodTemplate.ReturnType, null); extensionMethod.Flags = extensionMethodTemplate.Flags & ~MethodFlags.Static; // for generic methods, set the template args and params so the template data is included in the id and the method data if (extensionMethodTemplate2.IsGeneric) { extensionMethod.IsGeneric = true; if (specialization != null) { // set the template args for the specialized generic method extensionMethod.TemplateArguments = extensionMethodTemplate2.TemplateArguments; } else { // set the generic template params for the non-specialized generic method extensionMethod.TemplateParameters = extensionMethodTemplate2.TemplateParameters; } } // Get the id string extensionMethodTemplateId = reflector.ApiNamer.GetMemberName(extensionMethodTemplate); // write the element node writer.WriteStartElement("element"); writer.WriteAttributeString("api", extensionMethodTemplateId); writer.WriteAttributeString("source", "extension"); isExtensionMethod = true; reflector.WriteMember(extensionMethod); isExtensionMethod = false; writer.WriteEndElement(); }
private static void AddInterfaceImplementationWrapper(Class Class, Method intfMethod, Method baseMethod) { var d = new Duplicator(Class.DeclaringModule, Class); d.SkipBodies = true; var copy = d.VisitMethod(baseMethod); copy.Flags = MethodFlags.Private | MethodFlags.HideBySig | MethodFlags.Virtual | MethodFlags.NewSlot | MethodFlags.Final; copy.ImplementedInterfaceMethods = new MethodList(intfMethod); copy.Name = Identifier.For("InheritedInterfaceImplementationContractWrapper$" + intfMethod.Name.Name); copy.ClearBody(); copy.ThisParameter.Type = Class; var bodyBlock = new Block(new StatementList()); copy.Body = new Block(new StatementList(bodyBlock)); // add call to baseMethod var calledMethod = (baseMethod.TemplateParameters != null && baseMethod.TemplateParameters.Count > 0) ? baseMethod.GetTemplateInstance(Class, copy.TemplateParameters) : baseMethod; var argList = new ExpressionList(); for (int i = 0; i < copy.Parameters.Count; i++) { argList.Add(copy.Parameters[i]); } var callExpression = new MethodCall(new MemberBinding(copy.ThisParameter, calledMethod), argList); if (HelperMethods.IsVoidType(intfMethod.ReturnType)) { bodyBlock.Statements.Add(new ExpressionStatement(callExpression)); } else { bodyBlock.Statements.Add(new Return(callExpression)); } Class.Members.Add(copy); }
//===================================================================== /// <summary> /// Add extension method information to a type /// </summary> /// <param name="writer">The reflection data XML writer</param> /// <param name="type">the current type being extended</param> /// <param name="extensionMethodTemplate">A reference to the extension method. For generic methods, /// this is a reference to the non-specialized method, e.g. System.Linq.Enumerable.Select``2.</param> /// <param name="specialization">When the current type implements or inherits from a specialization /// of a generic type, this parameter has a TypeNode for the type used as a specialization of the /// generic type's first template parameter.</param> private void AddExtensionMethod(XmlWriter writer, TypeNode type, Method extensionMethodTemplate, TypeNode specialization) { // !EFW - Bug fix // Don't add extension method support to enumerations and static classes if(type != null && (type.NodeType == NodeType.EnumNode || (type.NodeType == NodeType.Class && type.IsAbstract && type.IsSealed))) return; // If this is a specialization of a generic method, construct a Method object that describes // the specialization. Method extensionMethodTemplate2 = extensionMethodTemplate; if(extensionMethodTemplate2.IsGeneric && specialization != null) { // The specialization type is the first of the method's template arguments TypeNodeList templateArgs = new TypeNodeList(); templateArgs.Add(specialization); // Add any additional template arguments for(int i = 1; i < extensionMethodTemplate.TemplateParameters.Count; i++) templateArgs.Add(extensionMethodTemplate.TemplateParameters[i]); extensionMethodTemplate2 = extensionMethodTemplate.GetTemplateInstance(type, templateArgs); } ParameterList extensionMethodTemplateParameters = extensionMethodTemplate2.Parameters; ParameterList extensionMethodParameters = new ParameterList(); for(int i = 1; i < extensionMethodTemplateParameters.Count; i++) { Parameter extensionMethodParameter = extensionMethodTemplateParameters[i]; extensionMethodParameters.Add(extensionMethodParameter); } Method extensionMethod = new Method(extensionMethodTemplate.DeclaringType, new AttributeList(), extensionMethodTemplate.Name, extensionMethodParameters, extensionMethodTemplate2.ReturnType, null); extensionMethod.Flags = extensionMethodTemplate.Flags & ~MethodFlags.Static; // For generic methods, set the template arguments and parameters so the template data is included in // the ID and the method data. if(extensionMethodTemplate2.IsGeneric) { extensionMethod.IsGeneric = true; if(specialization != null) { // Set the template arguments for the specialized generic method extensionMethod.TemplateArguments = extensionMethodTemplate2.TemplateArguments; } else { // Set the generic template parameters for the non-specialized generic method extensionMethod.TemplateParameters = extensionMethodTemplate2.TemplateParameters; } } // Get the ID string extensionMethodTemplateId = mrw.ApiNamer.GetMemberName(extensionMethodTemplate); // Write the element node writer.WriteStartElement("element"); writer.WriteAttributeString("api", extensionMethodTemplateId); writer.WriteAttributeString("source", "extension"); isExtensionMethod = true; mrw.WriteMember(extensionMethod); isExtensionMethod = false; writer.WriteEndElement(); }