Roslyn: How to inject "Namespace" to final type comes from CSharpScript ?

Created on 29 Dec 2016  路  2Comments  路  Source: dotnet/roslyn

Hi

based on this issue CS7021: You cannot declare namespace in script code I can not have any namespace in my text.

My goal is convert Text To Type.

please see code

`

public class Program
{
    public static void Main(string[] args)
    {
        var script = @" 
                    using System;
                    //namespace N     I CAN NOT HAVE NAMESPACE HERE BUT I NEED IT INTO RETURNED TYPE !
                    //{
                        public class A
                        {
                            public string B { get; set; }
                        }
                    //}
        ";
        CSharpScriptEngine.Execute(script);
        var typeOfA = (Type)CSharpScriptEngine.Execute("return typeof(A);");

    }
}

`

but final type (typeOfA) does not have any information about namespace so I want to know Is there any approach for this problem ?

Can I inject namespace info to final Type ?
some codes and extensions take my Types and shows error because namespace is null .

I think CodeDom in .NET framework is so better than Roslyn for this scenario because accept namespace, but I use .NET Core and I must use Roslyn unfortunately !

Does Roslyn have any solution ?!?!

Area-Interactive Question

Most helpful comment

@tmat

wow thanks you right

based on this tutorial Compiling C# Code Into Memory and Executing It with Roslyn

of course the code needs some changes for executing in .NET Core

   public class Program
    {
        public static void Main(string[] args)
        {
            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(@"
            using System.Collections.Generic;
            namespace ConsoleApp10
            {
                public class Address
                {
                    public string Street { get; set; }
                    public List<Phone> Phones { get; set; }

                    public Address()
                    {
                        Phones = new List<Phone>();
                    }
                }

                public class Phone
                {
                    public string Code { get; set; }
                    public string Number { get; set; }
                }

            }

            ");
            string assemblyName = Path.GetRandomFileName();
            MetadataReference[] references = {
                MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location)
            };
            CSharpCompilation compilation = CSharpCompilation.Create(
                assemblyName,
                new[] { syntaxTree },
                references,
                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
            using (var ms = new MemoryStream())
            {
                EmitResult result = compilation.Emit(ms);
                if (!result.Success)
                {
                    IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
                        diagnostic.IsWarningAsError ||
                        diagnostic.Severity == DiagnosticSeverity.Error);
                    foreach (Diagnostic diagnostic in failures)
                    {
                        Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
                    }
                }
                else
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(ms.ToArray()));
                    Type type = assembly.GetType("ConsoleApp10.Address");
                }
            }
            Console.Read();
        }
    }

All 2 comments

The Scripting API is not the right API to use for this purpose. If you need to control the specific form of the resulting metadata you can create a CSharpCompilation directly using CSharpCompilation.Create API and then emit the assembly via Compilation.Emit.

@tmat

wow thanks you right

based on this tutorial Compiling C# Code Into Memory and Executing It with Roslyn

of course the code needs some changes for executing in .NET Core

   public class Program
    {
        public static void Main(string[] args)
        {
            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(@"
            using System.Collections.Generic;
            namespace ConsoleApp10
            {
                public class Address
                {
                    public string Street { get; set; }
                    public List<Phone> Phones { get; set; }

                    public Address()
                    {
                        Phones = new List<Phone>();
                    }
                }

                public class Phone
                {
                    public string Code { get; set; }
                    public string Number { get; set; }
                }

            }

            ");
            string assemblyName = Path.GetRandomFileName();
            MetadataReference[] references = {
                MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location)
            };
            CSharpCompilation compilation = CSharpCompilation.Create(
                assemblyName,
                new[] { syntaxTree },
                references,
                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
            using (var ms = new MemoryStream())
            {
                EmitResult result = compilation.Emit(ms);
                if (!result.Success)
                {
                    IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
                        diagnostic.IsWarningAsError ||
                        diagnostic.Severity == DiagnosticSeverity.Error);
                    foreach (Diagnostic diagnostic in failures)
                    {
                        Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
                    }
                }
                else
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(ms.ToArray()));
                    Type type = assembly.GetType("ConsoleApp10.Address");
                }
            }
            Console.Read();
        }
    }

Was this page helpful?
0 / 5 - 0 ratings