Is there any way to load a .txt file as a class, which my main program can then call functions from? I'm basically trying to add mod support to my simple app, where the user can select options from each file. The file follows a similar (but not the same) format, with a bunch of voids (functions) that are called in the main program.
How can I do this? Is that even possible to do (probably not, answering my own question?), considering it wouldn't be compiled along with the rest of the program?
Thanks!
See me answer to this question: Compile a C# Array at runtime and use it in code?
Essentially, you would want to pull your text file into the CodeDom and compile it. After that, it would likely be helpful to create a few dynamic methods as execution helpers.
- Receive uploaded file
- Perform any needed validation on the file
- Read the file as a string into the CodeDom
- Deal with any compiler/structure errors
- Create helper methods using Linq expression trees or dynamic methods so that the linkage between the new class and existing code is bridged with a compiled object (otherwise, all the new methods would need to be invoked using reflection)
var csc = new CSharpCodeProvider( new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } } );
var cp = new CompilerParameters() {
GenerateExecutable = false,
OutputAssembly = outputAssemblyName,
GenerateInMemory = true
};
cp.ReferencedAssemblies.Add( "mscorlib.dll" );
cp.ReferencedAssemblies.Add( "System.dll" );
StringBuilder sb = new StringBuilder();
// The string can contain any valid c# code
sb.Append( "namespace Foo{" );
sb.Append( "using System;" );
sb.Append( "public static class MyClass{");
sb.Append( "}}" );
// "results" will usually contain very detailed error messages
var results = csc.CompileAssemblyFromSource( cp, sb.ToString() );
Also, see this topic: Implementing a scripting language in C#. IronPython with the DLR might be suitable for your needs.
You could load a text file and then use some Compiler-as-a-service (either Microsoft's pre-release Roslyn project or Mono.CSharp). Then you can take the compiled outputs and run them in your program.
If it's at all possible to get your user to hand you a compiled assembly instead of an uncompiled source file, you should consider the Managed Extensibility Framework or Mono.Addins.
The second approach (extension assemblies) seems better to me for at least two reasons: 1) your user can use whatever development environment they'd like to make sure their code compiles correctly before handing it over to you, and 2) you have less work to do to validate input and handle failures.
Use a Framework that Handles Plugins
The Managed Extensibility Framework is just what you're looking for
http://mef.codeplex.com/
The Managed Extensibility Framework (MEF) is a composition layer for .NET that improves the flexibility, maintainability and testability of large applications. MEF can be used for third-party plugin extensibility, or it can bring the benefits of a loosely-coupled plugin-like architecture to regular applications.
The MEF provides a well-defined architecture to support plugins in your application.
DLL vs. Text (Source Code)
The plugin developer is expected to provide a DLL containing the plugin code. However, if needed, you can compile source code into a DLL for them using Roslyn. Keep in mind that if you want to support receiving the plugin source code, you will also have to provide support for helping the user deal with compiler errors and debugging the plugin within your framework. It may be wiser to require them to provide a DLL.