예제 #1
0
        /// <summary>
        /// This method writes the generated code into a single file.
        /// </summary>
        private void WriteSingleCodeFile()
        {
            // Some assertions to make debugging easier.
            Debug.Assert(!string.IsNullOrEmpty(options.OutputLocation), "This action cannot be performed when output location is null or an empty string.");
            Debug.Assert(!string.IsNullOrEmpty(options.OutputFileName), "This action cannot be performed when output file name is null or an empty string");

            CodeExtension.RefineCodeWithShortName(codeCompileUnit);
            CodeNamespace codeNamespace = CodeExtension.GenerateCode(codeCompileUnit);

            codeNamespace.Name = options.TargetNamespace;
            CodeCompileUnit tempUnit = new CodeCompileUnit();

            tempUnit.Namespaces.Add(codeNamespace);

            // Get the destination file name.
            string fileName = CodeWriter.GetUniqueFileName(options.OutputLocation, options.OutputFileName, options.Language, options.OverwriteExistingFiles);
            // Create a StreamWriter for writing to the destination file.
            StreamWriter writer = new StreamWriter(fileName, false, Encoding.UTF8);

            try
            {
                // Write out the code to the destination file.
                provider.GenerateCodeFromCompileUnit(tempUnit, writer, codeGenerationOptions);
                // Flush all buffers in the writer.
                writer.Flush();
                // Initialize generatedFileNames array to hold the one and only one
                // file we just generated.
                generatedCodeFileNames = new string[1];
                // Finally add the file name to the generatedFileNames array.
                generatedCodeFileNames[0] = fileName;
            }
            catch (IOException e)
            {
                // Wrap the IOException in a CodeWriterException with little bit
                // more information.
                throw new CodeWriterException(
                          string.Format("An error occurred while trying write to file {0}: {1}", fileName, e.Message), e);
            }
            finally
            {
                // No matter what happens, dispose the stream writer and release the unmanaged
                // resources.
                writer.Dispose();
            }
        }
        /// <summary>
        /// Generates the <see cref="CodeCompileUnit"/> based on the provide context.
        /// </summary>
        /// <param name="codeGeneratorContext">The code generator context.</param>
        public CodeCompileUnit GenerateDataContractCode(ICodeGeneratorContext codeGeneratorContext)
        {
            CodeGenOptions codeGenOptions = codeGeneratorContext.CodeGenOptions;
            XmlSchemas     xmlSchemas     = codeGeneratorContext.XmlSchemas;

            CodeNamespace codeNamespace = new CodeNamespace();

            // Generate DataContracts
            const CodeGenerationOptions generationOptions = CodeGenerationOptions.GenerateProperties;
            var exporter = new XmlCodeExporter(codeNamespace);
            var importer = new XmlSchemaImporter(xmlSchemas, generationOptions, new ImportContext(new CodeIdentifiers(), false));

            // TypeName to XmlSchemaType mapping
            IDictionary <string, XmlSchemaType>    typeName2schemaTypeMapping         = codeGeneratorContext.TypeName2schemaTypeMapping;
            IDictionary <XmlQualifiedName, string> elementName2TypeNameMapping        = codeGeneratorContext.ElementName2TypeNameMapping;
            IDictionary <string, string>           elementName2TargetNamespaceMapping = codeGeneratorContext.ElementName2TargetNamespaceMapping;

            foreach (XmlSchema schema in xmlSchemas)
            {
                foreach (XmlSchemaElement element in schema.Elements.Values)
                {
                    XmlTypeMapping typeMapping = importer.ImportTypeMapping(element.QualifiedName);
                    if (element.IsAbstract)
                    {
                        continue;
                    }

                    exporter.ExportTypeMapping(typeMapping);
                    if (typeMapping.XsdTypeName == "anyType")
                    {
                        continue;                                       // ignore no type element
                    }
                    if (string.IsNullOrWhiteSpace(typeMapping.XsdTypeName))
                    {
                        throw new Exception("Cannot use anonymous type for Request/Response element: " + element.Name + ".");
                    }
                    typeName2schemaTypeMapping[typeMapping.XsdTypeName] = element.ElementSchemaType;
                    elementName2TypeNameMapping[element.QualifiedName]  = typeMapping.XsdTypeName;

                    elementName2TargetNamespaceMapping[element.QualifiedName.Name] = schema.TargetNamespace;
                }

                foreach (XmlSchemaType complexType in schema.SchemaTypes.Values)
                {
                    XmlTypeMapping typeMapping = importer.ImportSchemaType(complexType.QualifiedName);
                    if (DataContractGenerator.CouldBeAnArray(complexType))
                    {
                        continue;
                    }

                    exporter.ExportTypeMapping(typeMapping);
                    typeName2schemaTypeMapping[typeMapping.TypeName] = complexType;
                }
            }

            if (codeNamespace.Types.Count == 0)
            {
                throw new Exception("No types were generated.");
            }

            CodeCompileUnit codeCompileUnit = CodeExtension.GenerateDataContractCode(xmlSchemas);

            CodeExtension.RefineCode(codeCompileUnit);
            codeNamespace = CodeExtension.GenerateCode(codeCompileUnit);
            codeGeneratorContext.CodeTypeMap = DataContractGenerator.BuildCodeTypeMap(codeNamespace);

            // Generate interface code
            string                        wsdlFile          = codeGeneratorContext.CodeGenOptions.MetadataLocation;
            InterfaceContract             interfaceContract = ServiceDescriptionEngine.GetInterfaceContract(wsdlFile);
            CodeTypeDeclaration           codeType;
            CodeNamespaceImportCollection imports;

            this.buildInterfaceCode(codeGeneratorContext, interfaceContract, out codeType, out imports);
            imports.Add(new CodeNamespaceImport(Constants.C_SERVICE_STACK_COMMON_TYPES_NAMESPACE));
            codeNamespace = new CodeNamespace(codeGenOptions.ClrNamespace);
            codeNamespace.Types.Add(codeType);
            foreach (CodeNamespaceImport @import in imports)
            {
                codeNamespace.Imports.Add(@import);
            }
            codeCompileUnit.Namespaces.Add(codeNamespace);

            codeCompileUnit.ImplementsBaijiSerialization(codeGeneratorContext);

            // Import SOA common type namespace before removing code types
            List <CodeNamespace> toBeRemovedNamespaces = new List <CodeNamespace>();

            foreach (CodeNamespace @namespace in codeCompileUnit.Namespaces)
            {
                // Remove SOA common types since they have already been included in CSerivceStack DLL
                bool hasTypeRemoved = CodeExtension.RemoveSOACommonTypes(@namespace);
                if (hasTypeRemoved)
                {
                    @namespace.Imports.Add(new CodeNamespaceImport(Constants.C_SERVICE_STACK_COMMON_TYPES_NAMESPACE));
                }
                if (@namespace.Types.Count == 0)
                {
                    toBeRemovedNamespaces.Add(@namespace);
                }
            }

            foreach (CodeNamespace @namespace in toBeRemovedNamespaces)
            {
                codeCompileUnit.Namespaces.Remove(@namespace);
            }

            foreach (CodeNamespace @namespace in codeCompileUnit.Namespaces)
            {
                if (@namespace.Name != codeNamespace.Name)
                {
                    codeNamespace.Imports.Add(new CodeNamespaceImport(@namespace.Name));
                }
            }

            CodeExtension.RemoveDefaultTypes(codeCompileUnit);

            if (codeGeneratorContext.CodeGenOptions.AddCustomRequestInterface)
            {
                DataContractGenerator.ImplementCustomInterface(codeGeneratorContext, codeCompileUnit);
            }

            return(codeCompileUnit);
        }