Как использовать классы времени компиляции в скомпилированном классе во время выполнения? - PullRequest
0 голосов
/ 29 октября 2019

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

InvalidOperationException: Ошибка (CS0234): имя типа или пространства имен 'PremadeClass'(это имя класса) не существует в пространстве имен GameLevel (это имя пространства имен). Вам не хватает ссылки на сборку?

На основании предыдущих ошибок, которые у меня были с этим проектом, я предполагаю, что мне нужно сослаться на файл .dll для предварительно созданного класса в коде времени выполнения, ноне знаю, где Unity хранит их для каждого класса или даже генерирует их. Это может быть неправильно, так как оба класса, опять же, находятся в одном и том же пространстве имен, и я неопытен в C #.

Я написал свой код для компиляции, используя этот урок - проверьте его наподробнее об этом (это просто код с некоторыми пояснениями), но это самая важная часть:

public void Compile() {
  CSharpCodeProvider provider = new CSharpCodeProvider();
  CompilerParameters parameters = new CompilerParameters();
  //...
  parameters.ReferencedAssemblies.Add("path/UnityEngine.dll");
  parameters.OutputAssembly = "path/fileName.dll";
  parameters.GenerateInMemory = false; //generates actual file
  parameters.GenerateExecutable = false; //generates .dll instead of .exe
  //...
  parameters.OutputAssembly = Application.dataPath + className + ".dll";
  CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);
  //...
  Assembly assembly = results.CompiledAssembly;
  Type program = assembly.GetType("GameLevel." + className);
  MethodInfo excecuteMethod = program.GetMethod("Excecute");

  excecuteMethod.Invoke(null, null);
}

Это базовая структура готового класса:

namespace GameLevel
{
    public class PrecompiledClass
    {
         public void Foo() {
         }
    }
}

И это в основном то, как его использует код времени выполнения:

namespace GameLevel
{
    public class RuntimeClass
    {
         public void Foo() {
             new PrecompiledClass().Foo();
         }
    }
}

Я благодарен за ваши ответы!

1 Ответ

1 голос
/ 29 октября 2019

Поместите свои готовые классы в отдельную сборку (dll), затем включите эту dll в вашу parameters.ReferencedAssemblies.Add("path/Premade.dll")

Причина, по которой вы должны использовать отдельную сборку, заключается в том, что только те классы, к которым игрок должен получить доступ, будутбыть видимым для них.

...