I can't change other Class var value with CompileAssemblyFromSource

231 views Asked by At

i try to use CompileAssemblyFromSource to change 1 value at my main class. But when i compile i get error "Could not load file or assembly or one of its dependencies" and this only happens when i try change static value of other class. But if i return some output or wrote anything at Console from this FooClass than all work's fine. But how can i change value of other class?

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

namespace stringToCode
{
    class Program
    {
        public static int q = 0;
        static void Main(string[] args)
        {
            string source = "namespace stringToCode { public class FooClass { public void Execute() { Program.q = 1; } } }";

            Console.WriteLine("q=" + q);
            using (var foo = new CSharpCodeProvider())
            {
                var parameters = new CompilerParameters();
                parameters.GenerateInMemory = true;

                foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
                {
                    try
                    {
                        string location = assembly.Location;
                        if (!String.IsNullOrEmpty(location))
                        {
                            parameters.ReferencedAssemblies.Add(location);
                        }
                    }
                    catch (NotSupportedException)
                    {}
                } 

                var res = foo.CompileAssemblyFromSource(parameters ,source);
                var type = res.CompiledAssembly.GetType("FooClass"); //<- here i has error
                var obj = Activator.CreateInstance(type);
                var output = type.GetMethod("Execute").Invoke(obj, new object[] { });

                Console.WriteLine("q=" + q);
                Console.ReadLine();
            }
        }
    }
}
1

There are 1 answers

1
Hamlet Hakobyan On BEST ANSWER

You can't find the type because you have compilation error in your code.You can't access the classes in your current code in this manner. You should at least reference the current assembly in your in-memory assembly.

UPDATE

You have two issues in your code. First, you have to make the class Program public. Then you should specify the full name of type in GetType method.

This code works fine:

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

namespace stringToCode
{
    public class Program
    {
        public static int q = 0;
        static void Main(string[] args)
        {
            string source = "namespace stringToCode { public class FooClass { public void Execute() { Program.q = 1; } } }";

            Console.WriteLine("q=" + q);
            using (var foo = new CSharpCodeProvider())
            {
                var parameters = new CompilerParameters();
                parameters.GenerateInMemory = true;

                foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
                {
                    try
                    {
                        string location = assembly.Location;
                        if (!String.IsNullOrEmpty(location))
                        {
                            parameters.ReferencedAssemblies.Add(location);
                        }
                    }
                    catch (NotSupportedException)
                    {}
                } 

                var res = foo.CompileAssemblyFromSource(parameters ,source);
                var type = res.CompiledAssembly.GetType("stringToCode.FooClass"); //<- here i has error
                var obj = Activator.CreateInstance(type);
                var output = type.GetMethod("Execute").Invoke(obj, new object[] { });

                Console.WriteLine("q=" + q);
                Console.ReadLine();
            }
        }
    }
}