1

I am trying to add some specific modular functonality to my application, I need users to be able to create their own classes and then have them imported into the program at runtime, these classes will follow a specific template so I can call functions within their new class.

For example, a class could be: http://pastebin.com/90NTjia9

I would compile the class and then execute doSomething();

How would I achieve this in C#?

4
  • 1
    Typically you would do this by providing users with a dll that provides hooks in to your application. This enables them to create a dll which your app can then load. Commented Apr 2, 2012 at 16:56
  • I've used programs that let you simply drop a .cs file into a directory and have it compiled and run. Commented Apr 2, 2012 at 16:58
  • 1
    See Darin Dimitrov's answer here: stackoverflow.com/questions/4718329/… Commented Apr 2, 2012 at 17:02
  • You can check out how LINQPad works: linqpad.net/HowLINQPadWorks.aspx. Not quite the same thing, because users type the code in LINQPad's UI. Commented Apr 2, 2012 at 17:30

1 Answer 1

4

If your users have the necessary tools (such as Visual Studio, which they really should have if they're writing C# classes), they can supply you with a DLL, which you can then load dynamically:

private static T CreateInstance(string assemblyName, string typeName)
{
    var assembly = Assembly.LoadFrom(assemblyName);

    if (assembly == null)
        throw new InvalidOperationException(
           "The specified assembly '" + assemblyName + "' did not load.");

    Type type = assembly.GetType(typeName);
    if (type == null)
        throw new InvalidOperationException(
           "The specified type '" + typeName + "' was not found in assembly '" + assemblyName + "'");

    return (T)Activator.CreateInstance(type);
}

The T generic parameter is there so that you can pass an abstract class or interface to cast the type instance to:

public interface IDoSomething
{
    bool DoSomething();
}

Your users inherit from this interface when they write their own class:

public class UserDefinedClass : IDoSomething
{
    public bool DoSomething()
    {
        // Implementation here.
    }
}

This allows you to retain type safety and call the class methods directly, rather than relying on Reflection to do so.

If you really want your users to provide C# source, you can compile their class at runtime like this:

private Assembly BuildAssembly(string code)
{
    var provider = new CSharpCodeProvider();
    var compiler = provider.CreateCompiler();
    var compilerparams = new CompilerParameters();
    compilerparams.GenerateExecutable = false;
    compilerparams.GenerateInMemory = true;
    var results = compiler.CompileAssemblyFromSource(compilerparams, code);
    if (results.Errors.HasErrors)
    {
        var errors = new StringBuilder("Compiler Errors :\r\n");
        foreach (CompilerError error in results.Errors )
        {
            errors.AppendFormat("Line {0},{1}\t: {2}\n", 
                   error.Line, error.Column, error.ErrorText);
        }
        throw new Exception(errors.ToString());
    }
    else
    {
        return results.CompiledAssembly;
    }
}

Then, you just substitute the resulting assembly in the CreateInstance code above, instead of the externally-loaded assembly. Note that your users will still need to provide the appropriate using statements at the top of their class.

There are also places on the Internet that explain how to get an Eval() function in C#, in case you don't really need a full-blown class.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.