+2  A: 

It strikes me as a bad idea to actually upload into your App_Code folder. I'd use a separate folder which ASP.NET doesn't know anything about. That way you won't get the framework trying to automatically compile code for you.

You can easily compile and run code on the fly with CSharpCodeProvider - see my source code for Snippy for an example.

I hope this is only for internal (and authenticated) use though - I wouldn't recommend letting untrusted users execute their code on your web server. You can make it all slightly safer by running the code which very much reduced permissions, but you still risk the code tight-looping etc.

EDIT: In response to your updated question, you just need to provide the appropriate assembly to reference, containing IModule. See the CompilerParameters.ReferencedAssembles property.

Jon Skeet
Jon, ASP.NET provides functionality to declare your own build folders. :) No manual compilation is necessary.
Mehrdad Afshari
But I would want to have more control than that. In particular, I wouldn't want it restarting the app every time a new file was uploaded. I'd also want to make sure the new code only had access to the parts of my application that I wanted it to know about.
Jon Skeet
If that case, yes. This would work better. I also suggest adding some CAS attributes that explicitly deny access to all permissions except the ones really needed.
Mehrdad Afshari
@Jon Skeet. Updated my question. Mind taking a second look? :)
roosteronacid
+1  A: 
Assembly assembly = Assembly.Load(assemblyName);

IModule instance = assembly.CreateInstance(typeName) as IModule;

You could also use the Activatore.CreateInstance() method to create an instance without explicitly refering to the assembly.

Daniel Brückner
Hi Daniel. Thanks for your answer. I can't find anything in the C# framework named "Mediator.CreateInstance()" though. Could you elaborate?
roosteronacid
I wrote Mediator.CreateInstance() but meant Activator.CreateInstance(). See MSDN http://msdn.microsoft.com/de-de/library/system.activator.createinstance(VS.80,loband).aspx for reference.
Daniel Brückner
Assembly.Load("Test"); results in an error on my side of things.
roosteronacid
What exception? Security exception? Assembly not found? Is 'Test' really the name of the assembly or only the file name?
Daniel Brückner
I've tried the following: Assembly.Load("Test.cs"), Assembly.Load(MapPath("~/App_Code/") + "Test.cs") both resulting in Assembly not found
roosteronacid
Ahhhh ... this doesn't work, of course. Assembly.Load() is used to load compiled assemblies. I assumed the users will put DLLs like Plugins into the folder. As Jon already mentioned, you will have to first use the CSharpCodeProvider (http://msdn.microsoft.com/en-us/library/microsoft.csharp.csharpcodeprovider.aspx) to compile the source into a DLL.
Daniel Brückner
A: 

you can do it using reflection and here is a very simple method which will return you the instance of the module name [class name] you pass to the function

Public Shared Function GetDALInstance(ByVal moduleClassName As String) As IModule
        Dim className As String
        dim path as string = <<NamespacePath>>  
        className = Path + moduleClassName
        Return Assembly.Load(Path).CreateInstance(className)
    End Function

the above method is in vb.net you can simply convert this to c#

Vikram
A: 

I decided that classes which loads at run-time has to implement a given interface and that the name of the class has to be the same as the filename.

The folder the classes are uploaded to and compiled to is irrelevant.


Loading a compiled class (.dll) and instantiating it:

return (IInterfaceClassesMustImplement)Assembly
/* continued --> */ .LoadFile("c:\...\SomeClass.dll")
/* continued --> */ .CreateInstance("SomeClass");

Compile a class:

internal static class Compiler
{
    internal static void AssemblyFromFile(
        String classFilePath,
        String assemblyFilePath,
        String[] referencedAssemblies
    )
    {
        var cp = new CompilerParameters { OutputAssembly = assemblyFilePath };

        foreach (String ra in referencedAssemblies)
        {
            cp.ReferencedAssemblies.Add(ra);
        }

        CompilerResults cr = CodeDomProvider.CreateProvider("CSharp")
        /* continued --> */ .CompileAssemblyFromFile(cp, classFilePath);

        if (cr.Errors.Count > 0) // throw new Exception();
    }
}
roosteronacid