mercredi 28 février 2018

Skipping classes from service description when compiling in one assembly

short story: I am trying to import, at runtime, a bunch of asmx services exposed from one server. I want to put those in one assembly and load it runtime. Everything is fine until i get to the moment where i compile the imported service descriptions as most of them have few classes that are multiplicated across the different service descriptions.

Some code:

    static void Main(string[] args)
    {

        IEnumerable<ServiceData> services = GetServices();
        List<CodeCompileUnit> codeCompileUnits = new List<CodeCompileUnit>();

        foreach (ServiceData service in services)
        {
            Console.WriteLine($"Doing {service.Name.ToUpper()}");
            WebClient webClient = new System.Net.WebClient();
            webClient.Credentials = new NetworkCredential("username", "password", "domainname");
            System.IO.Stream stream;

            try
            {
                stream = webClient.OpenRead($"{service.Endpoint}?wsdl");
            }
            catch (WebException we)
            {
                Console.WriteLine(we.Message);
                Console.WriteLine(we.InnerException?.Message);
                continue;
            }

            ServiceDescription description = ServiceDescription.Read(stream);

            ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
            importer.ProtocolName = "Soap12"; // Use SOAP 1.2.
            importer.AddServiceDescription(description, null, null);

            importer.Style = ServiceDescriptionImportStyle.Client;

            importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;

            CodeNamespace nmspace = new CodeNamespace($"Name.Space.{service.Name}");
            CodeCompileUnit unit1 = new CodeCompileUnit();
            unit1.Namespaces.Add(nmspace);

            try
            {
                ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit1);
                if (warning == 0) // If zero then we are good to go
                {
                    codeCompileUnits.Add(unit1);
                }
            }
            catch (InvalidOperationException ioe)
            {
                Console.WriteLine(ioe.Message);
                Console.WriteLine(ioe.InnerException.Message);
            }

        }

        CodeDomProvider provider1 = CodeDomProvider.CreateProvider("CSharp" );

        string[] assemblyReferences = new string[5] { "System.dll", "System.Web.Services.dll", "System.Web.dll", "System.Xml.dll", "System.Data.dll" };
        CompilerParameters parms = new CompilerParameters(assemblyReferences);
        parms.OutputAssembly = "Assembly.dll";

        CompilerResults results = provider1.CompileAssemblyFromDom(parms, codeCompileUnits.ToArray());

        if (results.Errors.Count > 0)
        {
            foreach (CompilerError oops in results.Errors)
            {
                Console.WriteLine("========Compiler error============");
                Console.WriteLine(oops.ErrorText);
            }
            throw new System.Exception("Compile Error Occured calling webservice. Check Debug ouput window.");
        }
        else
        {

            Console.WriteLine("========Compiler error============");
            Console.WriteLine(results.PathToAssembly);
            Console.WriteLine(results.Output);

            //ToDo: Add the compiled assembly
            AppDomain.CurrentDomain.Load(results.CompiledAssembly.GetName());
        }

        var allTypes = AppDomain.CurrentDomain.GetAssemblies()
               .SelectMany(a => a.GetTypes().Where(c => c.IsClass && c.Namespace != null && c.Namespace.Contains(@"Name.Space"))).Select(t => new { Name = t.Name, Namespace = t.Namespace });

        //Assembly.GetExecutingAssembly().GetExportedTypes();

        foreach (var s in allTypes)
        Console.WriteLine($"{s.Namespace} => {s.Name}");

        Console.ReadLine();

    }

When I try to compile an assembly with

CompilerResults results = provider1.CompileAssemblyFromDom(parms, codeCompileUnits.ToArray());

I get few errors like this:

error CS0102: The type 'Name.Space.TypeNameGoesHere' already contains a definition for 'FielNameGoesHere'

So how do I force the compiler to ignore classes that are already in the namespace/assembly with the same name ?





Aucun commentaire:

Enregistrer un commentaire