I've just discovered the .NET ICodeCompiler (be aware that I know nothing about it, except that it can run programs within a program). How would I go about writing a scripting architecture around this?开发者_高级运维
Ideally, I would like the user to write some code that derives from an interface. This interface would be defined by me within my program (it cannot be edited by the user). The user would implement it, and the CompileEngine would run it. My program would then call the various methods they have implemented. Is this feasible?
eg. They would have to implement this:
public interface IFoo
{
void DoSomething();
}
I would then compile their implementation and instantiate their object:
// Inside my binary
IFoo pFooImpl = CUserFoo;
pFooImpl.DoSomething();
What you want to achieve is possible but BEWARE!! Everytime you compile the code, it gets compiled as an assembly and loaded into memory. If you change the "script" code and re-compile, it will be loaded again as another assembly. This can cause "memory leak" (although it is not a real leak) and there is no way to unload those unused assemblies.
The only solution is to create another AppDomain and load that assembly in that AppDomain and then unload if the code changes and do it again. But it is way more difficult to do.
UPDATE
For compiling have a look here: http://support.microsoft.com/kb/304655
Then you would have to load the assembly using Assembly.LoadFrom.
// assuming the assembly has only ONE class
// implementing the interface and method is void
private static void CallDoSomething(string assemblyPath, Type interfaceType,
string methodName, object[] parameters)
{
Assembly assembly = Assembly.LoadFrom(assemblyPath);
Type t = assembly.GetTypes().Where(x=>x.GetInterfaces().Count(y=>y==interfaceType)>0).FirstOrDefault();
if (t == null)
{
throw new ApplicationException("No type implements this interface");
}
MethodInfo mi = t.GetMethods().Where(x => x.Name == methodName).FirstOrDefault();
if (mi == null)
{
throw new ApplicationException("No such method");
}
mi.Invoke(Activator.CreateInstance(t), parameters);
}
If I understand correctly what you want to do, I think CodeDom and this article could help you. Is it what you're looking for?
精彩评论