コード例 #1
0
        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.");
                }
            }
        }
コード例 #2
0
        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;
                        }
                    }
                }
            }
        }
コード例 #3
0
        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);
                }
            }
        }
コード例 #4
0
        /// <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);
                    }
                }
            }
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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;
                                }
                            }
                        }
                    }
                }
            }
        }