1

I need compile and execute code via CSharpCodeProvider int the current context, for example:

using System;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

namespace ConsoleApplication1
{
    public class Program
    {
        public static void WriteMessage(string message)
        {
            Console.WriteLine(message);
        }

        static void Main(string[] args)
        {
            var compiler = new CSharpCodeProvider();
            var parms = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory = true,
            };

            parms.ReferencedAssemblies.Add("System.dll");

            var results = compiler.CompileAssemblyFromSource(parms, new string[]
            {@" using System;

                class MyClass
                {
                    public void Message(string message)
                    {
                        Program.WriteMessage(message);//Console.Write(message);
                    }               
                }"});

            if (results.Errors.Count == 0)
            {
                var myClass = results.CompiledAssembly.CreateInstance("MyClass");
                myClass.GetType().
                    GetMethod("Message").
                    Invoke(myClass, new[] {"Hello World!"});
            }
            else
            {
                foreach (var error in results.Errors)
                {
                    Console.WriteLine(error);
                }
            }
            Console.Read();
        }
    }
}

How you can see, i try to call Program.WriteMessage from the compiled code but i only get errors. Why?

2
  • what errors? post the errors!! I also see no reference to program.write message Commented Dec 1, 2013 at 13:04
  • By the way, the "context" in .NET-world is called your AppDomain. Commented Dec 1, 2013 at 13:19

1 Answer 1

2

The problem is that your compiled program tries to use a class (Program) from the current AppDomain, but when compiling, it does not know anything about it. In order to link the Program class and all other classes of the "compiling program" into the "compiled program", you need to add the current AppDomain's assembly (or, as the code below does, all assemblies) to the reference libraries before compiling your code. This answer tells you how to:

  1. link the current AppDomain into the compiled program and then
  2. load the program into the current AppDomain.

Specifically, you are missing this part for step 1:

    foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
    {
        try
        {
            string location = assembly.Location;
            if (!String.IsNullOrEmpty(location))
            {
                compilerParams.ReferencedAssemblies.Add(location);
            }
        }
        catch (NotSupportedException)
        {
            // this happens for dynamic assemblies, so just ignore it. 
        }
    } 

where compilerParams is your instance of CompilerParameters. You call it parms in your code.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.