7


私は C# で実行時にコードをコンパイルしようとしています。次に、コンパイルされたコードから関数を呼び出すか、元のコードで定義されているクラスを初期化します。
私が現在持っているコード:

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 ><");
        }
    }
}

これで、ランタイム ロード メソッド「Main」の実行が成功し、「Hello world」というメッセージが出力されます。問題はここから始まります。元のコードには、"SayHello" というメソッドがあります。ランタイムにロードされたコードからこのメソッドを呼び出したいと思います。
「DoTurn」メソッドのコメントを外すと、実行時にコンパイラ エラーが表示されます。

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



私の質問は - これは可能ですか、どのようにですか?

ランタイムにロードされたコードを同じ名前空間に置くことは役に立たない (そしてそれは理にかなっている) ので、それを行う正しい方法は何ですか?

ありがとう。

4

1 に答える 1

9

現在のアセンブリへの参照を追加すると、問題が解決しました。

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);

詳細: ユーザー定義関数を使用して実行時に c# をコンパイルする

于 2016-04-12T20:13:42.500 に答える