Wednesday, December 23, 2009

Generate assembly from C# code file dynamically

Simple code for creating the assemblies dynamically from a C# code file.



public bool CompileSource(string sourceFile, string targetAssembly, string [] references)
        {
            // delete existing assembly first
            if (File.Exists(targetAssembly))
            {
                try
                {
                    // this might fail if assembly is in use
                    File.Delete(targetAssembly);
                }
                catch (Exception ex)
                {
                    this.ErrorMessage = ex.Message;
                    return false;
                }
            }

            // read the C# source file
            StreamReader sr = new StreamReader(sourceFile);
            string fileContent = sr.ReadToEnd();
            sr.Close();

            // set up compiler and add required references
            ICodeCompiler compiler = new CSharpCodeProvider().CreateCompiler();
            CompilerParameters parameter = new CompilerParameters();
            parameter.OutputAssembly = targetAssembly;
            foreach(string reference in references)
            {
        parameter.ReferencedAssemblies.Add(reference);
            }
           
            // Do it: Final compilation to disk
            CompilerResults results = compiler.CompileAssemblyFromFile(parameter, sourceFile);

            if (File.Exists(targetAssembly))
                return true;

            // flatten the compiler error messages into a single string
            foreach (CompilerError err in results.Errors)
            {
                this.ErrorMessage += err.ToString() + "\r\n";
            }

            return false;
        }

Alternative to WSDL.exe tool for creating proxy classes from WSDL definition

Here is the code snippet which will help to generate C# proxy classes from WSDL definition without using the WSDL.exe tool


public bool GenerateWsdlProxyClass(string fileName, string generatedSourceFilename,
            string generatedNamespace)
        {
            // erase the source file
            if (File.Exists(generatedSourceFilename))
                File.Delete(generatedSourceFilename);

            FileStream stream = File.Open(fileName, FileMode.Open);

            ServiceDescription sd = null;

            try
            {
                sd = ServiceDescription.Read(stream);
            }
            catch (Exception ex)
            {
                this.ErrorMessage = "Wsdl Download failed: " + ex.Message;
                return false;
            }

            // create an importer and associate with the ServiceDescription
            ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
            importer.ProtocolName = "SOAP";
            importer.CodeGenerationOptions = CodeGenerationOptions.None;
            importer.AddServiceDescription(sd, null, null);

            // Download and inject any imported schemas (ie. WCF generated WSDL)           
            foreach (XmlSchema wsdlSchema in sd.Types.Schemas)
            {
                // Loop through all detected imports in the main schema
                foreach (XmlSchemaObject externalSchema in wsdlSchema.Includes)
                {
                    // Read each external schema into a schema object and add to importer
                    if (externalSchema is XmlSchemaImport)
                    {
                        Uri baseUri = new Uri(fileName);
                        Uri schemaUri = new Uri(baseUri, ((XmlSchemaExternal)externalSchema).SchemaLocation);

                        Stream schemaStream = File.Open(schemaUri.AbsolutePath, FileMode.Open);
                        System.Xml.Schema.XmlSchema schema = XmlSchema.Read(schemaStream, null);
                        importer.Schemas.Add(schema);
                    }
                }
            }

            // set up for code generation by creating a namespace and adding to importer
            CodeNamespace ns = new CodeNamespace(generatedNamespace);
            CodeCompileUnit ccu = new CodeCompileUnit();
            ccu.Namespaces.Add(ns);
            importer.Import(ns, ccu);

            // final code generation in specified language
            CSharpCodeProvider provider = new CSharpCodeProvider();
            IndentedTextWriter tw = new IndentedTextWriter(new StreamWriter(generatedSourceFilename));
            provider.GenerateCodeFromCompileUnit(ccu, tw, new CodeGeneratorOptions());

            tw.Close();
            stream.Close();
            return File.Exists(generatedSourceFilename);
        }