Как загрузить класс из файла .cs и использовать его в коде - PullRequest
0 голосов
/ 05 июня 2018

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

//some imports

public class Commands
{

     //a lot of commands

}

Я пытаюсь загрузить этот класс из файла с помощью CSharpCodeProvider или чего-либо еще и создать список команд.

Кусок кода из консольного приложения.

list<Commands> lst;

Вопрос в том, как я могу загрузить класс команд динамически (во время выполнения) (без перезапуска консольного приложения или запуска VS) и создать список команд?

Ответы [ 3 ]

0 голосов
/ 06 июня 2018

Чтобы загрузить класс c # из другого класса c #, вам нужно использовать «using»

using Commands;
public class class1
{
    private list<Commands>lst;
    //...
}
0 голосов
/ 06 июня 2018

Попробуйте этот пример, который я собрал и протестировал:

Построить program.cs как .Net Framework Console App, например, в Visual Studio.

// program.cs
using System;
using System.IO;
using System.CodeDom.Compiler;
using System.Reflection;

namespace RuntimeCompile
{
    class Program
    {
        static void Main(string[] args)
        {
            // Get a path to the file(s) to compile.
            FileInfo sourceFile = new FileInfo("mySource.cs");
            Console.WriteLine("Loading file: " + sourceFile.Exists);

            // Prepary a file path for the compiled library.
            string outputName = string.Format(@"{0}\{1}.dll",
                Environment.CurrentDirectory,
                Path.GetFileNameWithoutExtension(sourceFile.Name));

            // Compile the code as a dynamic-link library.
            bool success = Compile(sourceFile, new CompilerParameters()
            {
                GenerateExecutable = false, // compile as library (dll)
                OutputAssembly = outputName,
                GenerateInMemory = false, // as a physical file
            });

            if (success)
            {
                // Load the compiled library.
                Assembly assembly = Assembly.LoadFrom(outputName);

                // Now, since we didn't have reference to the library when building
                // the RuntimeCompile program, we can use reflection to create 
                // and use the dynamically created objects.
                Type commandType = assembly.GetType("Command");

                // Create an instance of the loaded class from its type information.
                object commandInstance = Activator.CreateInstance(commandType);

                // Invoke the method by name.
                MethodInfo sayHelloMethod = commandType.GetMethod("SayHello", BindingFlags.Public | BindingFlags.Instance);
                sayHelloMethod.Invoke(commandInstance, null); // no arguments, no return type
            }

            Console.WriteLine("Press any key to exit...");
            Console.Read();
        }

        private static bool Compile(FileInfo sourceFile, CompilerParameters options)
        {
            CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");

            CompilerResults results = provider.CompileAssemblyFromFile(options, sourceFile.FullName);

            if (results.Errors.Count > 0)
            {
                Console.WriteLine("Errors building {0} into {1}", sourceFile.Name, results.PathToAssembly);
                foreach (CompilerError error in results.Errors)
                {
                    Console.WriteLine("  {0}", error.ToString());
                    Console.WriteLine();
                }
                return false;
            }
            else
            {
                Console.WriteLine("Source {0} built into {1} successfully.", sourceFile.Name, results.PathToAssembly);
                return true;
            }
        }
    }
}

В выходном каталоге (bin) рядом с исполняемым файлом консольного приложения поместите текстовый файл с именем mySource.cs со следующим содержимым:

// mySource.cs
using System;

internal class Program
{
    static void Main()
    {
        Console.WriteLine("Hello from mySource!");
        Console.ReadLine();
    }
}

public class Command
{
    public void SayHello()
    {
        Console.WriteLine("Hello (Command)");
    }
}

Затем запустите первое консольное приложение и просмотрите еговыход.Должно появиться сообщение «Hello (Command)», показывающее, что код был правильно скомпилирован, загружен и выполнен.

В примере показано, как использовать CodeDom.Compiler для компиляции cs-файла во время выполнения, а затем загрузить его.как DLL для запуска кода внутри него.Имейте в виду, что обработка ошибок почти не была реализована.

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

0 голосов
/ 05 июня 2018

Вероятно, есть лучший способ достижения вашей общей цели, например внедрение зависимостей.

Однако вы можете сделать это с помощью ICodeCompiler.

См. Эту статью https://support.microsoft.com/en-ca/help/304655/how-to-programmatically-compile-code-using-c-compiler

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...