dff-solutions / shell.me

shell.me - your universal shell framework
MIT License
6 stars 1 forks source link

sand boxing plugins #9

Closed cburgdorf closed 12 years ago

cburgdorf commented 12 years ago

With the current implementation every plugin uses its own directory. Still if two plugins use the same assembly in different versions this will fail. The problem is at the very core of the CLR. Ideally we could unload assemblies so that everytime we use a command we just load those assemblies needed and immediately unload them afterwards. However, unloading assemblies is impossible with the current CLR. The only way to overcome this would be to load assemblies into another application domain and unload the whole application domain afterwards. However, this has it's own drawbacks because you need to use remoting than to communicate with the plugins.

If we want to go down this route we should check out: http://stackoverflow.com/questions/4145713/looking-for-a-practical-approach-to-sandboxing-net-plugins

However we might come up with a pseudo sand boxing approach where each plugin by convention sits in a directory named as the command name and then we delay the plugin loading until the very moment where the command is being used.

This will at least work for fire and forget usages (Read: one off usage, using the oss scheduler for example). If we would use it in non-interactive mode we would still clash into a version conflict, once we mix commands that share the same assembly in different versions. Another con would be the strict convention about the directory name of the plugin. However, we could overcome this using Mono.Cecil and a new command name approach:

Mono.Cecil is capable to read into an assembly without actually loading it (in contrast to System.Reflection). We could then say that we drop the Name property which is now responsible to make up the command name and instead use a convention where the command class name is used. E.g.

public class FooCommand
{
}

would automatically become the "foo" command (omitting the "Command" itself)

If we want to go that route we might want to look into this:

http://stackoverflow.com/questions/4371539/lazy-loading-dlls-with-mef?rq=1

Another option might be to preprocess all plugins (e.g. with Mono.Cecil) to produce new "runtime plugins" which are rewritten to not clash with the assemblies. However, this could be a rocky road as well.

If we want to go that route we might want to check out this: https://github.com/gluck/il-repack

cburgdorf commented 12 years ago

Ok, I think we should go the real sand boxing approach with different application domains. After all, that can't be too hard, really. Everything else comes with major drawbacks and makes shell.me less easy to grasp for users (e.g. why the hack can I mix versions if I use shell.me in non-interactive mode but not in interactive mode).

We should still be able to do our property injection magic, we just need to do the property injection from inside the command not outside it. With other words. ICommand should take an IEnumerable<string> and then use the PropertyWalker itself.