Недавно созданный C # Assembly доступ к предопределенным функциям - PullRequest
3 голосов
/ 08 февраля 2011

Хорошо, сначала я признаю, что не знаю подходящей терминологии для всего этого, поэтому я прошу прощения, если это уже решено, и я просто не использую соответствующие слова.

Я пытаюсь сделатьпрограмма на C #, которая позволяет коду C #, скомпилированному программой, выступать в качестве языка сценариев.

Вот мой пример кода для программы, которая загружает и компилирует код:

using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Reflection;

namespace RuntimeCompilation
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Program b = new Program();
            CompilerResults results = b.BuildAssembly("Class1.cs"); // compiles the class

            if (results.Errors.Count > 0)
            {
                System.Console.Out.WriteLine("Errors Follow:");
                String ErrorText = "";
                foreach (CompilerError CompErr in results.Errors)
                {
                    ErrorText = ErrorText +
                        "Line number " + CompErr.Line +
                        ", Error Number: " + CompErr.ErrorNumber +
                        ", '" + CompErr.ErrorText + ";" +
                        Environment.NewLine + Environment.NewLine;
                }
                System.Console.Out.WriteLine(ErrorText);
            }
            else
            {
                Assembly assembly = results.CompiledAssembly;
                foreach (Type type in assembly.GetTypes())
                {
                    System.Console.WriteLine("Type found: " + type.FullName);
                    System.Console.WriteLine("Creating Instance:");
                    System.Console.WriteLine("=======================");
                    assembly.CreateInstance(type.FullName);
                    System.Console.Out.WriteLine("=======================");
                    System.Console.Out.WriteLine("Done");
                }
            }
            System.Console.Out.WriteLine("DONE.");
        }

        // Compile a file of source and return the CompilerResults object.
        private CompilerResults BuildAssembly(string filename)
        {
            TextReader tr = new StreamReader(filename);
            string code = tr.ReadToEnd();
            CSharpCodeProvider provider = new CSharpCodeProvider();
            CompilerParameters compilerparams = new CompilerParameters();
            compilerparams.GenerateExecutable = false;
            compilerparams.GenerateInMemory = true;
            return provider.CompileAssemblyFromSource(compilerparams, code);
        }

        public bool iCanHasAccess()
        {
            return true;
        }
    }
}

Ивот класс, который он создает:

using System;
using RuntimeCompilation;

namespace RuntimeCompilation
{
    public class Class1
    {
        public Class1()
        {
            System.Console.WriteLine("This was instancialized");
            if (Program.iCanHasAccess())
                System.Console.WriteLine("I have access");
        }
    }
}

Ошибка, выдаваемая программой, заключается в том, что имя Program не существует в текущем контексте.Как я могу обеспечить, чтобы программа «script» имела доступ к функциям и членам программы компиляции?

Я пытаюсь разрешить простой способ с минимальными затратами времени выполнения, чтобы позволить пользователям изменять поведение компонентав рамках программы без необходимости перестроения.Если это невозможно с помощью сборок C #, я, вероятно, буду использовать LUA, но я бы хотел этого избежать.Поскольку я хотел бы, чтобы этот продукт работал на XBox360, необходимо скомпилировать проект WHOLE и сценарии вместе перед развертыванием через XNA.

1 Ответ

4 голосов
/ 08 февраля 2011

Вам понадобится ссылка на текущую сборку, то есть что-то вроде:

compilerparams.ReferencedAssemblies.Add("my.dll"); // or .exe

однако - следующее все равно не удастся:

        if (Program.iCanHasAccess())
            System.Console.WriteLine("I have access");

потому что iCanHasAccess() - это метод экземпляр , а не метод static.

...