void IDataContractGenerationExtension.GenerateContract(CodeCompileUnit compileUnit) { if (compileUnit == null) { throw new ArgumentNullException(nameof(compileUnit)); } foreach (var typeAccessModifierEntry in _typeAccessModifiers) { var typeName = typeAccessModifierEntry.Key; var accessModifier = typeAccessModifierEntry.Value; var typeDeclaration = compileUnit.FindTypeDeclaration(typeName); if (typeDeclaration == null) { throw new Exception($"Type '{typeName}' does not exist."); } switch (accessModifier) { case TypeAccessModifier.Internal: typeDeclaration.TypeAttributes &= ~TypeAttributes.VisibilityMask; typeDeclaration.TypeAttributes &= TypeAttributes.NotPublic; break; case TypeAccessModifier.Public: typeDeclaration.TypeAttributes &= ~TypeAttributes.VisibilityMask; typeDeclaration.TypeAttributes &= TypeAttributes.NotPublic; break; default: throw new Exception($"Access modifier '{accessModifier}' is not supported."); } } }
private void MapTypes(CodeCompileUnit compileUnit) { foreach (var complexType in _serviceModel.ComplexTypes) { var typeReference = _xsdDataContractImporter.GetCodeTypeReference(complexType.QualifiedName); var typeDeclaration = compileUnit.FindTypeDeclaration(typeReference.BaseType); // skip complex type for which no type was generated (eg. a List<>) if (typeDeclaration == null) { continue; } foreach (var property in typeDeclaration.Properties()) { var element = complexType.Elements.SingleOrDefault(p => p.Name == property.Name); if (element == null) { throw new Exception(); } if (element.MaxOccurs != 1) { continue; } if (!_xmlTypeMapping.TryGetValue(element.TypeCode, out var elementTypeMapping)) { continue; } if (element.MinOccurs == 0) { property.Type = elementTypeMapping.CodeTypeReference.ToNullable(); } else { property.Type = elementTypeMapping.CodeTypeReference; } if (property.GetStatements[0] is CodeMethodReturnStatement returnStatement && returnStatement.Expression != null) { if (returnStatement.Expression is CodeFieldReferenceExpression fieldReference) { var field = typeDeclaration.Fields().SingleOrDefault(p => p.Name == fieldReference.FieldName); if (field == null) { throw new Exception(); } field.Type = property.Type; } } } } }
void IDataContractGenerationExtension.GenerateContract(CodeCompileUnit compileUnit) { if (compileUnit == null) { throw new ArgumentNullException(nameof(compileUnit)); } foreach (var requiredMemberOverride in _requiredMemberOverrides) { var typeDeclaration = compileUnit.FindTypeDeclaration((CodeTypeName)requiredMemberOverride.Type); if (typeDeclaration == null) { throw new Exception($"Type '{requiredMemberOverride.Type}' does not exist."); } var member = typeDeclaration.FindMember(requiredMemberOverride.Member); if (member == null) { throw new Exception($"Member '{requiredMemberOverride.Member}' does not exist in type '{requiredMemberOverride.Type}'."); } var dataMemberAttribute = member.CustomAttributes.SingleOrDefault <CodeAttributeDeclaration>(p => p.Name == typeof(DataMemberAttribute).FullName); if (dataMemberAttribute == null) { dataMemberAttribute = new CodeAttributeDeclaration(new CodeTypeReference(typeof(DataMemberAttribute))); } var isRequiredArgument = dataMemberAttribute.Arguments.FindArgumentByName(nameof(DataMemberAttribute.IsRequired)); if (isRequiredArgument == null) { dataMemberAttribute.Arguments.Add(new CodeAttributeArgument( nameof(DataMemberAttribute.IsRequired), new CodePrimitiveExpression(requiredMemberOverride.IsRequired))); } else { isRequiredArgument.Value = new CodePrimitiveExpression(requiredMemberOverride.IsRequired); } } }
/// <summary> /// For those properties for which <see cref="DataMemberAttribute.IsRequired"/> is <c>true</c>, set <see cref="DataMemberAttribute.EmitDefaultValue"/> /// to <c>true</c>; otherwise, set <see cref="DataMemberAttribute.EmitDefaultValue"/> to <c>false</c>. /// </summary> /// <param name="compileUnit">The compile unit.</param> private void FixEmitDefaultValue(CodeCompileUnit compileUnit) { foreach (var complexType in _serviceModel.ComplexTypes) { var typeReference = _xsdDataContractImporter.GetCodeTypeReference(complexType.QualifiedName); var typeDeclaration = compileUnit.FindTypeDeclaration(typeReference.BaseType); // skip complex type for which no type was generated (eg. a List<>) if (typeDeclaration == null) { continue; } foreach (var property in typeDeclaration.Properties()) { var dataMemberAttribute = property.CustomAttributes.SingleOrDefault <CodeAttributeDeclaration>(p => p.Name == typeof(DataMemberAttribute).FullName); if (dataMemberAttribute == null) { continue; } var emitDefaultValue = IsRequired(dataMemberAttribute) && !ConsiderDefaultValueForTypeAsNoValue(compileUnit, _xmlTypeMappings, property.Type.BaseType); var emitDefaultValueArgument = dataMemberAttribute.Arguments.FindArgumentByName(nameof(DataMemberAttribute.EmitDefaultValue)); if (emitDefaultValueArgument == null) { emitDefaultValueArgument = new CodeAttributeArgument("EmitDefaultValue", new CodePrimitiveExpression(emitDefaultValue)); dataMemberAttribute.Arguments.Add(emitDefaultValueArgument); } else { emitDefaultValueArgument.Value = new CodePrimitiveExpression(emitDefaultValue); } } } }
private static bool ConsiderDefaultValueForTypeAsNoValue(CodeCompileUnit compileUnit, IDictionary <XmlTypeCode, XmlTypeMapping> xmlTypeMappings, string typeName) { if (typeName == typeof(short).FullName) { return(false); } if (typeName == typeof(int).FullName) { return(false); } if (typeName == typeof(long).FullName) { return(false); } if (typeName == typeof(float).FullName) { return(false); } if (typeName == typeof(ushort).FullName) { return(false); } if (typeName == typeof(uint).FullName) { return(false); } if (typeName == typeof(ulong).FullName) { return(false); } if (typeName == typeof(decimal).FullName) { return(false); } if (typeName == typeof(bool).FullName) { return(false); } if (typeName == typeof(DateTime).FullName) { return(false); } if (typeName == typeof(Guid).FullName) { return(false); } if (typeName == typeof(TimeSpan).FullName) { return(false); } if (typeName == typeof(string).FullName) { return(false); } if (typeName == "System.Collections.Generic.Dictionary`2") { return(true); } if (typeName == "System.Collections.Generic.List`1") { return(true); } var typeDeclaration = compileUnit.FindTypeDeclaration(typeName); if (typeDeclaration == null) { var typeMapping = FindTypeMapping(xmlTypeMappings, typeName); if (typeMapping == null) { throw new Exception($"Unable to determine whether '{typeName}' is a struct or enum."); } return(!(typeMapping.IsStruct || typeMapping.IsEnum)); } if (typeDeclaration.IsEnum) { foreach (CodeMemberField field in typeDeclaration.Members) { if (field.InitExpression is CodePrimitiveExpression primitiveExpression) { if (primitiveExpression.Value is long longValue) { // If one of the values defined by the num has value zero, then we consider the // default value as meaningful if (longValue == 0L) { return(false); } } else { throw new Exception($"Type '{primitiveExpression.Value.GetType()}' is not implemented."); } } } return(false); } return(typeDeclaration.IsStruct); }
void IDataContractGenerationExtension.GenerateContract(CodeCompileUnit compileUnit) { if (compileUnit == null) { throw new ArgumentNullException(nameof(compileUnit)); } foreach (var typeRenameEntry in _typeRenames) { var originalTypeName = (CodeTypeName)typeRenameEntry.Key; var newTypeName = (CodeTypeName)typeRenameEntry.Value; var typeDeclaration = compileUnit.FindTypeDeclaration(originalTypeName); if (typeDeclaration == null) { throw new Exception($"Type '{originalTypeName}' does not exist."); } // lookup the original namespace var originalNamespace = compileUnit.Namespaces().Single(n => n.Name == originalTypeName.Namespace); // if both the original and new type name are in the same namespace, then we need to // ensure the new type name doesn't already exist in the original namespace if (originalTypeName.Namespace == newTypeName.Namespace) { if (originalNamespace.Types().SingleOrDefault(t => t.Name == newTypeName.Type) != null) { throw new Exception($"Type '{newTypeName}' already exists."); } } else { var newNamespace = compileUnit.Namespaces().SingleOrDefault(n => n.Name == newTypeName.Namespace); if (newNamespace == null) { newNamespace = new CodeNamespace(newTypeName.Namespace); compileUnit.Namespaces.Add(newNamespace); } else { if (newNamespace.Types().Any(p => p.Name == newTypeName.Type)) { throw new Exception($"Type '{newTypeName}' already exists."); } } // add the type to the new namespace newNamespace.Types.Add(typeDeclaration); // remove the type from the original namespace originalNamespace.Types.Remove(typeDeclaration); // remove the original namespace if we just removed the last type from it if (originalNamespace.Types.Count == 0) { compileUnit.Namespaces.Remove(originalNamespace); } } // modify the name of the type typeDeclaration.Name = newTypeName.Type; var originalFullTypeName = originalTypeName.ToString(); var newFullTypeName = newTypeName.ToString(); // Updating a type declaration in CodeDOM does not update type parameters of that type foreach (var ns in compileUnit.Namespaces()) { foreach (CodeTypeDeclaration type in ns.Types) { foreach (CodeTypeMember member in type.Members) { if (member is CodeMemberField field) { if (field.Type.BaseType == originalFullTypeName) { field.Type.BaseType = newFullTypeName; } else { foreach (CodeTypeReference typeArgument in field.Type.TypeArguments) { if (typeArgument.BaseType == originalFullTypeName) { typeArgument.BaseType = newFullTypeName; } } } continue; } if (member is CodeMemberProperty property) { if (property.Type.BaseType == originalFullTypeName) { property.Type.BaseType = newFullTypeName; } } } } } } }