8


I'm trying to compile code at runtime in C#, then from the compiled code call a function or initialize a class which is defined in the original code.
The code I currently have:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;

namespace CTFGame
{
    class Program
    {
        static void Main(string[] args)
        {
            string code = @"

using System;

namespace CTFGame
{
    public class MyPlayer
    {
        public static void Main ()
        {
            Console.WriteLine(""Hello world"");
        }
        /*public void DoTurn ()
        {
            Program.SayHello();
        }*/
    }
}

";
            CSharpCodeProvider provider = new CSharpCodeProvider();
            CompilerParameters parameters = new CompilerParameters();
            parameters.GenerateInMemory = true;

            CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);
            if (results.Errors.HasErrors)
            {
                string errors = "";
                foreach (CompilerError error in results.Errors)
                {
                    errors += string.Format("Error #{0}: {1}\n", error.ErrorNumber, error.ErrorText);
                }
                Console.Write(errors);
            }
            else
            {
                Assembly assembly = results.CompiledAssembly;
                Type program = assembly.GetType("CTFGame.MyPlayer");
                MethodInfo main = program.GetMethod("Main");
                main.Invoke(null, null);
            }
        }

        public static void SayHello()
        {
            Console.WriteLine("I'm awesome ><");
        }
    }
}

Now, Running the runtime loaded method 'Main' is a success, and the message "Hello world" is printed. The problem starts here: in the original code I have a method called "SayHello". I want to call this method from my runtime loaded code.
If I uncomment the "DoTurn" method, a compiler error will show in runtime:

Error #CS0103: The name 'Program' does not exist in the current context



My question is - is this possible, and how?

Putting the runtime loaded code in the same namespace doesn't help (and that makes sense), so what is the correct way to do that?

Thanks.

Yotam Salmon
  • 2,400
  • 22
  • 36
  • 2
    You need to add a reference to your assembly. – SLaks Apr 12 '16 at 19:53
  • 1
    Consider using Roslyn. – SLaks Apr 12 '16 at 19:53
  • Perhaps you should think about getting your code to compile at all before trying to dynamically compile it. – David L Apr 12 '16 at 19:53
  • @DavidL Already did it. The code compiles nicely. – Yotam Salmon Apr 12 '16 at 19:55
  • Someone correct me if i am wrong, but what you're trying to do would seem to cause a circular dependency. You're assembly that you compile on the fly doesn't know about the currently executing assembly, but you're trying to call a method on the current assembly from the compiled code. – Jonesopolis Apr 12 '16 at 19:58
  • @Jonesopolis In the current situation it doesn't. I don't think a circular dependency will be caused, because you don't make the original assembly get compiled again. Think of it as having class A, inside class A you initialize class B, and you pass the current instance of class A to the constructor of B so it knows you're there... – Yotam Salmon Apr 12 '16 at 20:01
  • Thanks, @SLaks. You are in fact right. I added a reference to the current running assembly and it works like a charm. I'm going to post it as an answer so others can benefit from it. Thanks a lot! – Yotam Salmon Apr 12 '16 at 20:10

1 Answers1

9

Adding a reference to the current assembly solved the problem:

CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateInMemory = true;                
//The next line is the addition to the original code
parameters.ReferencedAssemblies.Add(Assembly.GetEntryAssembly().Location);

More about: Compiling c# at runtime with user defined functions

Yotam Salmon
  • 2,400
  • 22
  • 36