Reputation: 43
I want to load a class form a .cs file and use it in another code.
Assume I have a .cs file which contains code like that:
//some imports
public class Commands
{
//a lot of commands
}
What I am trying is to load this class from a file using CSharpCodeProvider or whatever and create a list of Commands.
A piece of code from a console app.
list<Commands> lst;
The question is how can I load Commands class dynamically (at runtime) (without restarting the console app or starting VS) and create the list of Commands?
Upvotes: 2
Views: 8460
Reputation: 1461
Try this example, which I have put together and tested:
Build program.cs as a .Net Framework Console App
in e.g. 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;
}
}
}
}
In the output directory (bin), next to the console app executable place a text file named mySource.cs with this content:
// 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)");
}
}
Then run the first console app and observe it's output. It should log "Hello (Command)", showing that the code was correctly compiled, loaded and executed.
The example shows how to use the CodeDom.Compiler
to compile a cs-file at runtime and then load it as dll to run code within it. Be aware, that almost no error handling was implemented.
This should answer the question, but there may still be better approaches to handling your use-case. In case of plugin loading it makes sense to use interfaces which are added as a reference to both assemblies to avoid the use of reflection, etc.
Upvotes: 8
Reputation: 19
To load the c# class from another c# class you need to use "using"
using Commands;
public class class1
{
private list<Commands>lst;
//...
}
Upvotes: -2
Reputation: 5016
There is probably a better way to achieve your overall goal, like dependency injection.
However, you can do it with the ICodeCompiler.
See this article https://support.microsoft.com/en-ca/help/304655/how-to-programmatically-compile-code-using-c-compiler
Upvotes: 1