protected override void OnFieldNameChanged(CodeTypeMemberExtension memberExtension, string oldName, string newName) { // Field can be either a body member or a message header. // First see if the field is a body member. CodeAttributeDeclaration bodyMember = memberExtension.FindAttribute("System.ServiceModel.MessageBodyMemberAttribute"); // If this is a body member, modify the MessageBodyMemberAttribute to include the wire name. if (bodyMember != null) { CodeAttributeDeclaration newBodyMember = new CodeAttributeDeclaration("System.ServiceModel.MessageBodyMemberAttribute", new CodeAttributeArgumentExtended("Name", new CodePrimitiveExpression(oldName), true)); memberExtension.AddAttribute(newBodyMember); } // Now check whether the field is a message header. CodeAttributeDeclaration header = memberExtension.FindAttribute("System.ServiceModel.MessageHeaderAttribute"); if (header != null) { CodeAttributeDeclaration newHeader = new CodeAttributeDeclaration("System.ServiceModel.MessageHeaderAttribute", new CodeAttributeArgumentExtended("Name", new CodePrimitiveExpression(oldName), true)); memberExtension.AddAttribute(newHeader); } // Make sure the field name change is reflected in the field name references. ConvertFieldReferencesInConstructors(memberExtension.Parent.Constructors, oldName, newName); }
protected override void OnFieldNameChanged(CodeTypeMemberExtension memberExtension, string oldName, string newName) { OnFieldOrPropertyNameChanged(memberExtension, oldName, newName); // Make sure the field name change is reflected in the field name references. ConvertFieldReferencesInConstructors(memberExtension.Parent.Constructors, oldName, newName); }
protected override bool CanConvertMember(CodeTypeMemberExtension memberExtension) { if (memberExtension.Kind == CodeTypeMemberKind.Method) { return ((memberExtension.ExtendedObject.Attributes & MemberAttributes.Public) == MemberAttributes.Public); } return false; }
protected override bool CanConvertMember(CodeTypeMemberExtension memberExtension) { // For Data Contracts we change only the public proeperties/fields. if (memberExtension.Kind == CodeTypeMemberKind.Property || memberExtension.Kind == CodeTypeMemberKind.Field) { return ((memberExtension.ExtendedObject.Attributes & MemberAttributes.Public) == MemberAttributes.Public); } return true; }
/// <summary> /// This method checks whether a given CodeTypeMember contains any attributes that will /// prevent from converting its type from an array to a collection. /// </summary> private bool HasInvalidAttributes(CodeTypeMemberExtension memberExtension) { if (memberExtension.FindAttribute("System.Xml.Serialization.XmlChoiceIdentifierAttribute") != null) { return(true); } else if (memberExtension.FindAttribute("System.Xml.Serialization.XmlIgnoreAttribute") != null) { return(true); } else { return(false); } }
/// <summary> /// Converts all member names in a given enumeration to Pascal case. /// </summary> private void ConvertEnumMemberNames() { // Do this for all members in the enumeration. foreach (CodeTypeMember member in type.Members) { // Cast the member reference to CodeTypeMemberExtension type. CodeTypeMemberExtension ext = (CodeTypeMemberExtension)member; // We perform the pascal case conversion only in the public members. if ((ext.ExtendedObject.Attributes & MemberAttributes.Public) == MemberAttributes.Public || (ext.ExtendedObject.Attributes & MemberAttributes.Final) == MemberAttributes.Final) { // Call the function for converting an enum member name to Pascal case. ConvertEnumMemberName(ext); } } }
protected override bool CanConvertMember(CodeTypeMemberExtension memberExtension) { // We can only convert the fields. if (memberExtension.Kind == CodeTypeMemberKind.Field) { if (memberExtension.FindAttribute("System.ServiceModel.MessageBodyMemberAttribute") != null) { return true; } if (memberExtension.FindAttribute("System.ServiceModel.MessageHeaderAttribute") != null) { return true; } } return false; }
protected override bool CanConvertMember(CodeTypeMemberExtension memberExtension) { // We can only convert the fields. if (memberExtension.Kind == CodeTypeMemberKind.Field) { if (memberExtension.FindAttribute("System.ServiceModel.MessageBodyMemberAttribute") != null) { return(true); } if (memberExtension.FindAttribute("System.ServiceModel.MessageHeaderAttribute") != null) { return(true); } } return(false); }
/// <summary> /// Gets the modified CodeDom CodeNamespace instance without additional wrappers. /// This instance can be used with standard code generation APIs to emit the final /// code. /// </summary> public CodeNamespace UnwrapCodeDomTree() { foreach (CodeTypeDeclaration ctd in codeNamespace.Types) { // Unwrap the members. for (int j = 0; j < ctd.Members.Count; j++) { CodeTypeMemberExtension memberExt = ctd.Members[j] as CodeTypeMemberExtension; if (memberExt != null) { ctd.Members[j] = memberExt.ExtendedObject; } } } return(codeNamespace); }
protected override void OnPropertyNameChanged(CodeTypeMemberExtension memberExtension, string oldName, string newName) { OnFieldOrPropertyNameChanged(memberExtension, oldName, newName); CodeMemberProperty property = (CodeMemberProperty)memberExtension.ExtendedObject; // Look up for the data binding statement and change the property name there. foreach (CodeStatement statement in property.SetStatements) { CodeExpressionStatement expStatement = statement as CodeExpressionStatement; // Continue if the statement is not a CodeExpressionStatement. if (expStatement == null) { continue; } CodeMethodInvokeExpression miExp = expStatement.Expression as CodeMethodInvokeExpression; // Continue if the statement is not a CodeMethodInvokeExpression. if (miExp == null) { continue; } // Modify the property name in parameters. foreach (CodeExpression pExp in miExp.Parameters) { CodePrimitiveExpression priExp = pExp as CodePrimitiveExpression; // Continue if the statment is not a CodePrimitiveExpression. if (priExp == null) { continue; } if (priExp.Value.ToString() == oldName) { priExp.Value = newName; } } } }
/// <summary> /// This methods adds CodeTypeMemberExtension to all CodeTypeMembers in a /// given type. /// </summary> private static void ExtendTypeMembers(CodeTypeExtension typeExtension) { CodeTypeDeclaration type = (CodeTypeDeclaration)typeExtension.ExtendedObject; for (int i = 0; i < type.Members.Count; i++) { CodeTypeMember member = type.Members[i]; CodeTypeMemberExtension memberExtension = new CodeTypeMemberExtension(member, typeExtension); // Add the member to the correct filtered collection. if (memberExtension.Kind == CodeTypeMemberKind.Field) { typeExtension.Fields.Add(memberExtension); } else if (memberExtension.Kind == CodeTypeMemberKind.Property) { typeExtension.Properties.Add(memberExtension); } else if (memberExtension.Kind == CodeTypeMemberKind.Method) { typeExtension.Methods.Add(memberExtension); } else if (memberExtension.Kind == CodeTypeMemberKind.Constructor || memberExtension.Kind == CodeTypeMemberKind.StaticConstructor) { typeExtension.Constructors.Add(memberExtension); } else if (memberExtension.Kind == CodeTypeMemberKind.Event) { typeExtension.Events.Add(memberExtension); } else { typeExtension.Unknown.Add(memberExtension); } // Finally update the collection item reference. type.Members[i] = memberExtension; } }
/// <summary> /// Adds a new attribute to a attributes collection or modify an existing attribute. /// It checks whether a given attribute exists and adds it if its not there. If it is there, then it will /// add the arguments available in the new attribute but not available in the existing attribute. /// </summary> /// <param name="attribute">Attribute to add.</param> /// <returns> /// Returns true if the attribute is actually added to the object. Otherwise returns false. /// The latter happens when the attribute already exists in the object. /// </returns> public bool AddAttribute(CodeAttributeDeclaration attribDecl) { if (attribDecl == null) { throw new ArgumentException("attribDecl could not be null."); } CodeAttributeDeclaration existingAttrib = FindAttribute(attribDecl.Name); // Can we see a matching, existing attribute? Then try to sync the attributes. if (existingAttrib != null) { CodeTypeMemberExtension.SyncSourceAttributes(existingAttrib, attribDecl); return(false); } else { // Add this to the CustomAttributes collection. extendedObject.CustomAttributes.Add(attribDecl); attributesCache.Add(attribDecl.Name, attribDecl); return(true); } }
private void OnFieldOrPropertyNameChanged(CodeTypeMemberExtension memberExtension, string oldName, string newName) { // Here we basically have two cases. Array and non-array. // If it's an non-array type, we have to decorate it with either // XmlAttributeAttribute attribute or XmlElementAttribute attribute. // If it's an array type we have to decorate it with XmlArrayAttribute // attribute. // There is one quickie we can try before anything nevertheless. // Regardless of whether the member type is an array type or not // member can already have an XmlElementAttribute attribute. // If this is the case we can simply add the XML type name information to that. CodeAttributeDeclaration xmlElementAttribute = memberExtension.FindAttribute("System.Xml.Serialization.XmlElementAttribute"); if (xmlElementAttribute != null) { // Create a new CodeAttributeDeclaration with required arguments xmlElementAttribute = new CodeAttributeDeclaration("System.Xml.Serialization.XmlElementAttribute", new CodeAttributeArgumentExtended( "ElementName", new CodePrimitiveExpression(oldName), true)); // Add the newly created attribute to CodeTypeMember. memberExtension.AddAttribute(xmlElementAttribute); // No need to proceed, so simply return. return; } // Let's first handle the non-array case. // And then handl the array case. if (!PascalCaseConverterHelper.IsArray(memberExtension)) { // See if we can spot the XmlAttributeAttribute attribute. CodeAttributeDeclaration xmlAttribute = memberExtension.FindAttribute("System.Xml.Serialization.XmlAttributeAttribute"); // If we could, then let's add the AttributeName argument to it. if (xmlAttribute != null) { // Create a new CodeAttributeDeclaration with required arguments. CodeAttributeDeclaration xmlAttributeAttribute = new CodeAttributeDeclaration("System.Xml.Serialization.XmlAttributeAttribute", new CodeAttributeArgumentExtended( "AttributeName", new CodePrimitiveExpression(oldName), true)); // Add the newly created attribute to CodeTypeMember. memberExtension.AddAttribute(xmlAttributeAttribute); } else { // We arrive here if we could not spot the XmlAttributeAttribute attribute. // Therefore we can add the XmlElementAttribute attribute. // However, before we proceed we have to check whether any of the following attributes // already exists. if (memberExtension.FindAttribute("System.Xml.Serialization.XmlTextAttribute") != null || memberExtension.FindAttribute("System.Xml.Serialization.XmlIgnoreAttribute") != null || memberExtension.FindAttribute("System.Xml.Serialization.XmlAnyElementAttribute") != null || memberExtension.FindAttribute("System.Xml.Serialization.XmlAnyAttributeAttribute") != null) { // We cannot add XmlElementAttribute attribute here. return; } // Create a new CodeAttributeDeclaration with required arguments xmlElementAttribute = new CodeAttributeDeclaration("System.Xml.Serialization.XmlElementAttribute", new CodeAttributeArgumentExtended( "ElementName", new CodePrimitiveExpression(oldName), true)); // Add the newly created attribute to CodeTypeMember. memberExtension.AddAttribute(xmlElementAttribute); } } else { // We arrive here if we have an array type. // We can proceed to adding XmlArrayAttribue attribute if following attributes are // not present. if (memberExtension.FindAttribute("System.Xml.Serialization.XmlTextAttribute") != null || memberExtension.FindAttribute("System.Xml.Serialization.XmlAnyElementAttribute") != null || memberExtension.FindAttribute("System.Xml.Serialization.XmlAnyAttributeAttribute") != null) { // We cannot add XmlElementAttribute attribute here. return; } // Create a new CodeAttributeDeclaration for XmlArrayAttribute with required arguments. CodeAttributeDeclaration xmlArrayAttribute = new CodeAttributeDeclaration("System.Xml.Serialization.XmlArrayAttribute", new CodeAttributeArgumentExtended( "ElementName", new CodePrimitiveExpression(oldName), true)); // Add the newly created CodeAttributeDeclaration to the attributes collection of // CodeTypeMemeber. memberExtension.AddAttribute(xmlArrayAttribute); } }
protected override void OnMethodNameChanged(CodeTypeMemberExtension memberExtension, string oldName, string newName) { // NOP }
protected override void OnEnumMemberChanged(CodeTypeMemberExtension memberExtension, string oldName, string newName) { // Fix references found in DefaultValue attributes. foreach (CodeTypeExtension type in Code.DataContracts) { foreach (CodeTypeMemberExtension member in type.Fields) { CodeAttributeDeclaration attribute = member.FindAttribute("System.ComponentModel.DefaultValueAttribute"); if (attribute == null) { continue; } CodeAttributeArgument argument = attribute.Arguments[0]; CodeFieldReferenceExpression argumentValue = argument.Value as CodeFieldReferenceExpression; if (argumentValue == null) { continue; } string baseTypeName = ((CodeTypeReferenceExpression)argumentValue.TargetObject).Type.BaseType; string nameOfTypeInAttribute = PascalCaseConverterHelper.GetPascalCaseName(baseTypeName); string nameOfTypeBeingChanged = memberExtension.Parent.ExtendedObject.Name; if (argumentValue.FieldName == oldName && nameOfTypeInAttribute == nameOfTypeBeingChanged) { argumentValue.FieldName = newName; } } // Fix references found in constructor where default values are set. // This is required for fixed references to enum values. // e.g. <xs:attribute ref="xlink:type" fixed="simple"/> foreach (CodeTypeMemberExtension ctorExtension in type.Constructors) { // Get a reference to the actual constructor object. CodeConstructor constructor = (CodeConstructor)ctorExtension.ExtendedObject; // Do this for all statements we have in the constructor. foreach (CodeStatement statement in constructor.Statements) { // Is this an assign statement? CodeAssignStatement assignStatement = statement as CodeAssignStatement; if (assignStatement != null) { // Do we have a field reference on the right side of the assignment statement? CodeFieldReferenceExpression fieldRef = assignStatement.Right as CodeFieldReferenceExpression; if (fieldRef != null) { // Does the referenced field belong to a type reference? if (typeof(CodeTypeReferenceExpression) == fieldRef.TargetObject.GetType()) { string baseTypeName = ((CodeTypeReferenceExpression)fieldRef.TargetObject).Type.BaseType; string nameOfTypeForField = PascalCaseConverterHelper.GetPascalCaseName(baseTypeName); string nameOfTypeBeingChanged = memberExtension.Parent.ExtendedObject.Name; // Change the field name if it's changed. if (fieldRef.FieldName == oldName && nameOfTypeForField == nameOfTypeBeingChanged) { // Fix the field name first. fieldRef.FieldName = newName; // Also fix the name in the type reference. ((CodeTypeReferenceExpression)fieldRef.TargetObject).Type.BaseType = nameOfTypeForField; } } } } } } } // Before adding the XmlEnumAttribute attribute to the CodeTypeMember // we have to make sure that the following attributes are not present. // If the 'XmlEnumAttribute' is already present the original value was not a valid name // and there should be no attempt to perform a rename. if (memberExtension.FindAttribute("System.Xml.Serialization.XmlAttributeAttribute") != null || memberExtension.FindAttribute("System.Xml.Serialization.XmlAnyElementAttribute") != null || memberExtension.FindAttribute("System.Xml.Serialization.XmlAnyAttributeAttribute") != null || memberExtension.FindAttribute("System.Xml.Serialization.XmlEnumAttribute") != null) { // We cannot proceed. return; } // Create a CodeAttributeDeclaration for XmlEnumAttribute attribute and // add it to the attributes collection. CodeAttributeDeclaration xmlEnum = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlEnumAttribute"); xmlEnum.Arguments.Add(new CodeAttributeArgumentExtended("Name", new CodePrimitiveExpression(oldName), true)); // Finally add it to the custom attributes collection. memberExtension.AddAttribute(xmlEnum); }
/// <summary> /// This method ensures that we can generate a collection type to substitute /// given members type. /// </summary> private bool IsConvertibleMemeber(CodeTypeMemberExtension memberExtension) { if (memberExtension.Kind == CodeTypeMemberKind.Field) { CodeMemberField field = (CodeMemberField)memberExtension.ExtendedObject; if (field.Type.ArrayElementType == null) { return false; } // The field is not convertible if it is used in a property that has invalid attributes. foreach (CodeTypeMemberExtension parent in memberExtension.Parent.Properties) { CodeMemberProperty property = (CodeMemberProperty)parent.ExtendedObject; foreach (CodeStatement statement in property.GetStatements) { // Get the return statement for the property getter. CodeMethodReturnStatement returnStatement = statement as CodeMethodReturnStatement; if (returnStatement != null) { // Do we have a field reference on the right side of the assignment statement? CodeFieldReferenceExpression fieldRef = returnStatement.Expression as CodeFieldReferenceExpression; if (fieldRef != null) { // Is the field referenced the one we are checking? if (fieldRef.FieldName == field.Name) { // Does the property have invalid attributes? if (HasInvalidAttributes(parent)) { // If so, then the field should not be processed! return false; } } } } } } // Return true if we don't have any invalid attributes. return !HasInvalidAttributes(memberExtension); } else if (memberExtension.Kind == CodeTypeMemberKind.Property) { CodeMemberProperty property = (CodeMemberProperty)memberExtension.ExtendedObject; if (property.Type.ArrayElementType == null) { return false; } // Return true if we don't have any invalid attributes. return !HasInvalidAttributes(memberExtension); } else if (memberExtension.Kind == CodeTypeMemberKind.Method) { return true; } else if (memberExtension.Kind == CodeTypeMemberKind.Constructor || memberExtension.Kind == CodeTypeMemberKind.StaticConstructor) { return true; } else { // Currently we support only converting properties, fields and methods. return false; } }
private void CreateServiceType() { // We can create the service type(s) only if we have one or more service // contract. if (code.ServiceContracts.Count > 0) { // Take a reference to the first ServiceContract available. // IMPORTANT!:(Currently we only support single service type) // May be want to support multiple service contracts in the next version. CodeTypeExtension srvContract = code.ServiceContracts[0]; // Notify if srvContract is null. This would mean that we have constructed a bad // GeneratedCode instance from our CodeFactory. Debug.Assert(srvContract != null, "Generated service contract could not be null."); // Construct the service type name by removing the leading "I" character from // the service contract name that was added for generation of the interface. string srvTypeName = srvContract.ExtendedObject.Name.Substring(1); // Create a new instance of CodeTypeDeclaration type representing the service type. CodeTypeDeclaration srvType = new CodeTypeDeclaration(srvTypeName); // Also wrap the CodeTypeDeclaration in an extension. CodeTypeExtension typeExt = new CodeTypeExtension(srvType); // This class. srvType.IsClass = true; switch (options.MethodImplementation) { case MethodImplementation.PartialClassMethodCalls: // The service type is partial so that the implementation methods can be written in separate file. srvType.IsPartial = true; break; case MethodImplementation.AbstractMethods: // The service type is abstract so that the operation methods can be made abstract. srvType.TypeAttributes |= TypeAttributes.Abstract; break; } // And this implements the service contract interface. if (code.CodeLanguauge == CodeLanguage.VisualBasic) { srvType.Members.Add(new CodeSnippetTypeMember("Implements " + srvContract.ExtendedObject.Name)); } else { srvType.BaseTypes.Add(new CodeTypeReference(srvContract.ExtendedObject.Name)); } // Now itterate the srvContractObject.Members and add each and every method in // the service contract type to the new type being created. foreach (CodeTypeMemberExtension methodExtension in srvContract.Methods) { // Get a referece to the actual CodeMemberMethod object extended // by ext. CodeMemberMethod method = methodExtension.ExtendedObject as CodeMemberMethod; // Create a new CodeMemeberMethod and copy the attributes. CodeMemberMethod newMethod = new CodeMemberMethod(); newMethod.Name = method.Name; // Implemented method has to be public. newMethod.Attributes = MemberAttributes.Public; // Notify that this member is implementing a method in the service contract. if (code.CodeLanguauge == CodeLanguage.VisualBasic) { newMethod.ImplementationTypes.Add(new CodeTypeReference(srvContract.ExtendedObject.Name)); } else { newMethod.ImplementationTypes.Add(srvType.BaseTypes[0]); } // Add all parametes to the newly created method. foreach (CodeParameterDeclarationExpression cpde in method.Parameters) { newMethod.Parameters.Add(cpde); } // Set the return type. newMethod.ReturnType = method.ReturnType; switch (options.MethodImplementation) { case MethodImplementation.PartialClassMethodCalls: { // Gather the parameters from the operation to pass into the implementation method. IEnumerable<CodeArgumentReferenceExpression> parameters = newMethod.Parameters .OfType<CodeParameterDeclarationExpression>() .Select(p => new CodeArgumentReferenceExpression(p.Name)); // Create an expression to invoke the implementation method. CodeMethodInvokeExpression methodInvocation = new CodeMethodInvokeExpression(null, newMethod.Name + "Implementation", parameters.ToArray()); // Check if the method has a return type. if (newMethod.ReturnType.BaseType != "System.Void") { // Make sure the call to the implementation method is returned. CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement(methodInvocation); newMethod.Statements.Add(returnStatement); } else { // Add the call to the implementation method without a return. newMethod.Statements.Add(methodInvocation); } } break; case MethodImplementation.NotImplementedException: { // Create a new code statement to throw NotImplementedExcption. CodeThrowExceptionStatement niex = new CodeThrowExceptionStatement( new CodeObjectCreateExpression( new CodeTypeReference(typeof(NotImplementedException)), new CodeExpression[] { }) ); // Add it to the statements collection in the new method. newMethod.Statements.Add(niex); } break; case MethodImplementation.AbstractMethods: { // No statement is required for the abstract methods. newMethod.Attributes |= MemberAttributes.Abstract; break; } } // Wrap the CodeMemberMethod in an extension. This could be useful for other extensions. CodeTypeMemberExtension newMethodExt = new CodeTypeMemberExtension(newMethod, typeExt); srvType.Members.Add(newMethodExt); } // Add the ServiceBehaviorAttribute attribute. CodeAttributeDeclaration serviceBehaviorAttribute = new CodeAttributeDeclaration( new CodeTypeReference(typeof(ServiceBehaviorAttribute))); if (!string.IsNullOrEmpty(options.InstanceContextMode)) { CodeTypeReferenceExpression instanceContextModeEnum = new CodeTypeReferenceExpression(typeof(InstanceContextMode)); CodeFieldReferenceExpression instanceContextModeValue = new CodeFieldReferenceExpression(instanceContextModeEnum, options.InstanceContextMode); CodeAttributeArgument instanceContextModeArgument = new CodeAttributeArgument("InstanceContextMode", instanceContextModeValue); serviceBehaviorAttribute.Arguments.Add(instanceContextModeArgument); } if (!string.IsNullOrEmpty(options.ConcurrencyMode)) { CodeTypeReferenceExpression concurrencyModeEnum = new CodeTypeReferenceExpression(typeof(ConcurrencyMode)); CodeFieldReferenceExpression concurrencyModeValue = new CodeFieldReferenceExpression(concurrencyModeEnum, options.ConcurrencyMode); CodeAttributeArgument concurrencyModeArgument = new CodeAttributeArgument("ConcurrencyMode", concurrencyModeValue); serviceBehaviorAttribute.Arguments.Add(concurrencyModeArgument); } if (!options.UseSynchronizationContext) { CodeAttributeArgument useSynchronizationContextAttribute = new CodeAttributeArgument("UseSynchronizationContext", new CodePrimitiveExpression(false)); serviceBehaviorAttribute.Arguments.Add(useSynchronizationContextAttribute); } typeExt.AddAttribute(serviceBehaviorAttribute); this.serviceTypeName = srvType.Name; // Finally add the newly created type to the code being generated. code.ServiceTypes.Add(typeExt); } }
protected override void OnEnumMemberChanged(CodeTypeMemberExtension memberExtension, string oldName, string newName) { // Fix references found in DefaultValue attributes. foreach (CodeTypeExtension type in Code.DataContracts) { foreach (CodeTypeMemberExtension member in type.Fields) { CodeAttributeDeclaration attribute = member.FindAttribute("System.ComponentModel.DefaultValueAttribute"); if (attribute == null) continue; CodeAttributeArgument argument = attribute.Arguments[0]; CodeFieldReferenceExpression argumentValue = argument.Value as CodeFieldReferenceExpression; if (argumentValue == null) continue; string baseTypeName = ((CodeTypeReferenceExpression)argumentValue.TargetObject).Type.BaseType; string nameOfTypeInAttribute = PascalCaseConverterHelper.GetPascalCaseName(baseTypeName); string nameOfTypeBeingChanged = memberExtension.Parent.ExtendedObject.Name; if (argumentValue.FieldName == oldName && nameOfTypeInAttribute == nameOfTypeBeingChanged) { argumentValue.FieldName = newName; } } // Fix references found in constructor where default values are set. // This is required for fixed references to enum values. // e.g. <xs:attribute ref="xlink:type" fixed="simple"/> foreach (CodeTypeMemberExtension ctorExtension in type.Constructors) { // Get a reference to the actual constructor object. CodeConstructor constructor = (CodeConstructor)ctorExtension.ExtendedObject; // Do this for all statements we have in the constructor. foreach (CodeStatement statement in constructor.Statements) { // Is this an assign statement? CodeAssignStatement assignStatement = statement as CodeAssignStatement; if (assignStatement != null) { // Do we have a field reference on the right side of the assignment statement? CodeFieldReferenceExpression fieldRef = assignStatement.Right as CodeFieldReferenceExpression; if (fieldRef != null) { // Does the referenced field belong to a type reference? if (typeof(CodeTypeReferenceExpression) == fieldRef.TargetObject.GetType()) { string baseTypeName = ((CodeTypeReferenceExpression)fieldRef.TargetObject).Type.BaseType; string nameOfTypeForField = PascalCaseConverterHelper.GetPascalCaseName(baseTypeName); string nameOfTypeBeingChanged = memberExtension.Parent.ExtendedObject.Name; // Change the field name if it's changed. if (fieldRef.FieldName == oldName && nameOfTypeForField == nameOfTypeBeingChanged) { // Fix the field name first. fieldRef.FieldName = newName; // Also fix the name in the type reference. ((CodeTypeReferenceExpression)fieldRef.TargetObject).Type.BaseType = nameOfTypeForField; } } } } } } } // Before adding the XmlEnumAttribute attribute to the CodeTypeMember // we have to make sure that the following attributes are not present. // If the 'XmlEnumAttribute' is already present the original value was not a valid name // and there should be no attempt to perform a rename. if (memberExtension.FindAttribute("System.Xml.Serialization.XmlAttributeAttribute") != null || memberExtension.FindAttribute("System.Xml.Serialization.XmlAnyElementAttribute") != null || memberExtension.FindAttribute("System.Xml.Serialization.XmlAnyAttributeAttribute") != null || memberExtension.FindAttribute("System.Xml.Serialization.XmlEnumAttribute") != null) { // We cannot proceed. return; } // Create a CodeAttributeDeclaration for XmlEnumAttribute attribute and // add it to the attributes collection. CodeAttributeDeclaration xmlEnum = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlEnumAttribute"); xmlEnum.Arguments.Add(new CodeAttributeArgumentExtended("Name", new CodePrimitiveExpression(oldName), true)); // Finally add it to the custom attributes collection. memberExtension.AddAttribute(xmlEnum); }
/// <summary> /// This method checks whether a given CodeTypeMember contains any attributes that will /// prevent from converting its type from an array to a collection. /// </summary> private bool HasInvalidAttributes(CodeTypeMemberExtension memberExtension) { if (memberExtension.FindAttribute("System.Xml.Serialization.XmlChoiceIdentifierAttribute") != null) { return true; } else if (memberExtension.FindAttribute("System.Xml.Serialization.XmlIgnoreAttribute") != null) { return true; } else { return false; } }
private void ConvertEnumMemberName(CodeTypeMemberExtension typeMemberExtension) { // Get a copy of the original type name. string oldName = typeMemberExtension.ExtendedObject.Name; // Change the field/property name to Pascal case. string newName = PascalCaseConverterHelper.GetPascalCaseName(oldName); if (oldName != newName) { typeMemberExtension.ExtendedObject.Name = newName; OnEnumMemberChanged(typeMemberExtension, oldName, newName); } }
protected override bool CanConvertMember(CodeTypeMemberExtension memberExtension) { return(memberExtension.Kind == CodeTypeMemberKind.Method); }
private void CreateServiceType() { // We can create the service type(s) only if we have one or more service // contract. if (code.ServiceContracts.Count > 0) { // Take a reference to the first ServiceContract available. // IMPORTANT!:(Currently we only support single service type) // May be want to support multiple service contracts in the next version. CodeTypeExtension srvContract = code.ServiceContracts[0]; // Notify if srvContract is null. This would mean that we have constructed a bad // GeneratedCode instance from our CodeFactory. Debug.Assert(srvContract != null, "Generated service contract could not be null."); // Construct the service type name by removing the leading "I" character from // the service contract name that was added for generation of the interface. string srvTypeName = srvContract.ExtendedObject.Name.Substring(1); // Create a new instance of CodeTypeDeclaration type representing the service type. CodeTypeDeclaration srvType = new CodeTypeDeclaration(srvTypeName); // Also wrap the CodeTypeDeclaration in an extension. CodeTypeExtension typeExt = new CodeTypeExtension(srvType); // This class. srvType.IsClass = true; switch (options.MethodImplementation) { case MethodImplementation.PartialClassMethodCalls: // The service type is partial so that the implementation methods can be written in separate file. srvType.IsPartial = true; break; case MethodImplementation.AbstractMethods: // The service type is abstract so that the operation methods can be made abstract. srvType.TypeAttributes |= TypeAttributes.Abstract; break; } // And this implements the service contract interface. if (code.CodeLanguauge == CodeLanguage.VisualBasic) { srvType.Members.Add(new CodeSnippetTypeMember("Implements " + srvContract.ExtendedObject.Name)); } else { srvType.BaseTypes.Add(new CodeTypeReference(srvContract.ExtendedObject.Name)); } // Now itterate the srvContractObject.Members and add each and every method in // the service contract type to the new type being created. foreach (CodeTypeMemberExtension methodExtension in srvContract.Methods) { // Get a referece to the actual CodeMemberMethod object extended // by ext. CodeMemberMethod method = methodExtension.ExtendedObject as CodeMemberMethod; // Create a new CodeMemeberMethod and copy the attributes. CodeMemberMethod newMethod = new CodeMemberMethod(); newMethod.Name = method.Name; // Implemented method has to be public. newMethod.Attributes = MemberAttributes.Public; // Notify that this member is implementing a method in the service contract. if (code.CodeLanguauge == CodeLanguage.VisualBasic) { newMethod.ImplementationTypes.Add(new CodeTypeReference(srvContract.ExtendedObject.Name)); } else { newMethod.ImplementationTypes.Add(srvType.BaseTypes[0]); } // Add all parametes to the newly created method. foreach (CodeParameterDeclarationExpression cpde in method.Parameters) { newMethod.Parameters.Add(cpde); } // Set the return type. newMethod.ReturnType = method.ReturnType; switch (options.MethodImplementation) { case MethodImplementation.PartialClassMethodCalls: { // Gather the parameters from the operation to pass into the implementation method. IEnumerable <CodeArgumentReferenceExpression> parameters = newMethod.Parameters .OfType <CodeParameterDeclarationExpression>() .Select(p => new CodeArgumentReferenceExpression(p.Name)); // Create an expression to invoke the implementation method. CodeMethodInvokeExpression methodInvocation = new CodeMethodInvokeExpression(null, newMethod.Name + "Implementation", parameters.ToArray()); // Check if the method has a return type. if (newMethod.ReturnType.BaseType != "System.Void") { // Make sure the call to the implementation method is returned. CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement(methodInvocation); newMethod.Statements.Add(returnStatement); } else { // Add the call to the implementation method without a return. newMethod.Statements.Add(methodInvocation); } } break; case MethodImplementation.NotImplementedException: { // Create a new code statement to throw NotImplementedExcption. CodeThrowExceptionStatement niex = new CodeThrowExceptionStatement( new CodeObjectCreateExpression( new CodeTypeReference(typeof(NotImplementedException)), new CodeExpression[] { }) ); // Add it to the statements collection in the new method. newMethod.Statements.Add(niex); } break; case MethodImplementation.AbstractMethods: { // No statement is required for the abstract methods. newMethod.Attributes |= MemberAttributes.Abstract; break; } } // Wrap the CodeMemberMethod in an extension. This could be useful for other extensions. CodeTypeMemberExtension newMethodExt = new CodeTypeMemberExtension(newMethod, typeExt); srvType.Members.Add(newMethodExt); } // Add the ServiceBehaviorAttribute attribute. CodeAttributeDeclaration serviceBehaviorAttribute = new CodeAttributeDeclaration( new CodeTypeReference(typeof(ServiceBehaviorAttribute))); if (!string.IsNullOrEmpty(options.InstanceContextMode)) { CodeTypeReferenceExpression instanceContextModeEnum = new CodeTypeReferenceExpression(typeof(InstanceContextMode)); CodeFieldReferenceExpression instanceContextModeValue = new CodeFieldReferenceExpression(instanceContextModeEnum, options.InstanceContextMode); CodeAttributeArgument instanceContextModeArgument = new CodeAttributeArgument("InstanceContextMode", instanceContextModeValue); serviceBehaviorAttribute.Arguments.Add(instanceContextModeArgument); } if (!string.IsNullOrEmpty(options.ConcurrencyMode)) { CodeTypeReferenceExpression concurrencyModeEnum = new CodeTypeReferenceExpression(typeof(ConcurrencyMode)); CodeFieldReferenceExpression concurrencyModeValue = new CodeFieldReferenceExpression(concurrencyModeEnum, options.ConcurrencyMode); CodeAttributeArgument concurrencyModeArgument = new CodeAttributeArgument("ConcurrencyMode", concurrencyModeValue); serviceBehaviorAttribute.Arguments.Add(concurrencyModeArgument); } if (!options.UseSynchronizationContext) { CodeAttributeArgument useSynchronizationContextAttribute = new CodeAttributeArgument("UseSynchronizationContext", new CodePrimitiveExpression(false)); serviceBehaviorAttribute.Arguments.Add(useSynchronizationContextAttribute); } typeExt.AddAttribute(serviceBehaviorAttribute); this.serviceTypeName = srvType.Name; // Finally add the newly created type to the code being generated. code.ServiceTypes.Add(typeExt); } }
protected abstract void OnPropertyNameChanged(CodeTypeMemberExtension memberExtension, string oldName, string newName);
protected override bool CanConvertMember(CodeTypeMemberExtension memberExtension) { return (memberExtension.Kind == CodeTypeMemberKind.Method); }
private static void HandleShouldSerialize(CodeTypeMemberExtension fieldPropertyMember) { CodeTypeDeclaration type = fieldPropertyMember.Parent.ExtendedObject as CodeTypeDeclaration; if (type == null) { return; } CodeAttributeDeclaration arrayAttribute = fieldPropertyMember.FindAttribute("System.Xml.Serialization.XmlArrayItemAttribute"); if (arrayAttribute == null) { return; } CodeAttributeArgument isNullableArgument = arrayAttribute.FindArgument("IsNullable"); if (isNullableArgument == null) { return; } bool isNullable = (bool)((CodePrimitiveExpression)isNullableArgument.Value).Value; if (isNullable) { return; } string name = fieldPropertyMember.ExtendedObject.Name; CodeMemberMethod shouldSerializeMethod = new CodeMemberMethod { Attributes = MemberAttributes.Public, Name = "ShouldSerialize" + name, ReturnType = new CodeTypeReference(typeof(bool)) }; CodeThisReferenceExpression thisReference = new CodeThisReferenceExpression(); CodeFieldReferenceExpression collectionField = new CodeFieldReferenceExpression(thisReference, name); CodeBinaryOperatorExpression notNullExpression = new CodeBinaryOperatorExpression { Left = collectionField, Operator = CodeBinaryOperatorType.IdentityInequality, Right = new CodePrimitiveExpression(null) }; CodeBinaryOperatorExpression greaterThanZeroExpression = new CodeBinaryOperatorExpression { Left = new CodePropertyReferenceExpression(collectionField, "Count"), Operator = CodeBinaryOperatorType.GreaterThan, Right = new CodePrimitiveExpression(0) }; CodeBinaryOperatorExpression andExpression = new CodeBinaryOperatorExpression { Left = notNullExpression, Operator = CodeBinaryOperatorType.BooleanAnd, Right = greaterThanZeroExpression }; CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement(andExpression); shouldSerializeMethod.Statements.Add(returnStatement); type.Members.Add(shouldSerializeMethod); }
private static void HandleShouldSerialize(CodeTypeMemberExtension fieldPropertyMember) { CodeTypeDeclaration type = fieldPropertyMember.Parent.ExtendedObject as CodeTypeDeclaration; if (type == null) return; CodeAttributeDeclaration arrayAttribute = fieldPropertyMember.FindAttribute("System.Xml.Serialization.XmlArrayItemAttribute"); if (arrayAttribute == null) return; CodeAttributeArgument isNullableArgument = arrayAttribute.FindArgument("IsNullable"); if (isNullableArgument == null) return; bool isNullable = (bool)((CodePrimitiveExpression)isNullableArgument.Value).Value; if (isNullable) return; string name = fieldPropertyMember.ExtendedObject.Name; CodeMemberMethod shouldSerializeMethod = new CodeMemberMethod { Attributes = MemberAttributes.Public, Name = "ShouldSerialize" + name, ReturnType = new CodeTypeReference(typeof(bool)) }; CodeThisReferenceExpression thisReference = new CodeThisReferenceExpression(); CodeFieldReferenceExpression collectionField = new CodeFieldReferenceExpression(thisReference, name); CodeBinaryOperatorExpression notNullExpression = new CodeBinaryOperatorExpression { Left = collectionField, Operator = CodeBinaryOperatorType.IdentityInequality, Right = new CodePrimitiveExpression(null) }; CodeBinaryOperatorExpression greaterThanZeroExpression = new CodeBinaryOperatorExpression { Left = new CodePropertyReferenceExpression(collectionField, "Count"), Operator = CodeBinaryOperatorType.GreaterThan, Right = new CodePrimitiveExpression(0) }; CodeBinaryOperatorExpression andExpression = new CodeBinaryOperatorExpression { Left = notNullExpression, Operator = CodeBinaryOperatorType.BooleanAnd, Right = greaterThanZeroExpression }; CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement(andExpression); shouldSerializeMethod.Statements.Add(returnStatement); type.Members.Add(shouldSerializeMethod); }
/// <summary> /// Contains the core logic for converting a method name to Pascal case. /// </summary> private void ConvertMethod(CodeTypeMemberExtension memberExtension) { // Get a copy of the original name. string oldName = memberExtension.ExtendedObject.Name; // Change the method name to Pascal case. string newName = PascalCaseConverterHelper.GetPascalCaseMethodName(oldName); if (oldName != newName) { memberExtension.ExtendedObject.Name = newName; OnMethodNameChanged(memberExtension, oldName, newName); } }
protected abstract bool CanConvertMember(CodeTypeMemberExtension memberExtension);
protected abstract void OnEnumMemberChanged(CodeTypeMemberExtension memberExtension, string oldName, string newName);
protected override void OnPropertyNameChanged(CodeTypeMemberExtension memberExtension, string oldName, string newName) { // NOP }
/// <summary> /// This method ensures that we can generate a collection type to substitute /// given members type. /// </summary> private bool IsConvertibleMemeber(CodeTypeMemberExtension memberExtension) { if (memberExtension.Kind == CodeTypeMemberKind.Field) { CodeMemberField field = (CodeMemberField)memberExtension.ExtendedObject; if (field.Type.ArrayElementType == null) { return(false); } // The field is not convertible if it is used in a property that has invalid attributes. foreach (CodeTypeMemberExtension parent in memberExtension.Parent.Properties) { CodeMemberProperty property = (CodeMemberProperty)parent.ExtendedObject; foreach (CodeStatement statement in property.GetStatements) { // Get the return statement for the property getter. CodeMethodReturnStatement returnStatement = statement as CodeMethodReturnStatement; if (returnStatement != null) { // Do we have a field reference on the right side of the assignment statement? CodeFieldReferenceExpression fieldRef = returnStatement.Expression as CodeFieldReferenceExpression; if (fieldRef != null) { // Is the field referenced the one we are checking? if (fieldRef.FieldName == field.Name) { // Does the property have invalid attributes? if (HasInvalidAttributes(parent)) { // If so, then the field should not be processed! return(false); } } } } } } // Return true if we don't have any invalid attributes. return(!HasInvalidAttributes(memberExtension)); } else if (memberExtension.Kind == CodeTypeMemberKind.Property) { CodeMemberProperty property = (CodeMemberProperty)memberExtension.ExtendedObject; if (property.Type.ArrayElementType == null) { return(false); } // Return true if we don't have any invalid attributes. return(!HasInvalidAttributes(memberExtension)); } else if (memberExtension.Kind == CodeTypeMemberKind.Method) { return(true); } else if (memberExtension.Kind == CodeTypeMemberKind.Constructor || memberExtension.Kind == CodeTypeMemberKind.StaticConstructor) { return(true); } else { // Currently we support only converting properties, fields and methods. return(false); } }