C# ICodeCompiler - 运行一个类

4
我刚刚发现了.NET ICodeCompiler(请注意,除了它可以在程序内运行程序之外,我对它一无所知)。如果要围绕它编写一个脚本架构,应该怎么做呢?
理想情况下,我希望用户编写一些从接口派生的代码。这个接口将由我在我的程序中定义(用户不能编辑它)。用户将实现它,CompileEngine将运行它。然后,我的程序将调用他们已经实现的各种方法。这可行吗?
例如,他们将不得不实现这个:
public interface IFoo
{
  void DoSomething();
}

我会编译他们的实现并实例化他们的对象:
// Inside my binary
IFoo pFooImpl = CUserFoo;
pFooImpl.DoSomething();
2个回答

2
您想要实现的是可能的,但注意!!每次编译代码时,它都会被编译为一个程序集并加载到内存中。如果您更改“脚本”代码并重新编译,则会再次作为另一个程序集加载。这可能会导致“内存泄漏”(虽然不是真正的泄漏),而且没有办法卸载那些未使用的程序集。

唯一的解决方案是创建另一个AppDomain,在该AppDomain中加载该程序集,然后在代码更改时卸载并再次执行。但这要困难得多。

更新

有关编译,请查看此处: http://support.microsoft.com/kb/304655

然后,您需要使用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);
    }

请执行。我也想知道这是否会将我在代码中设计的任何接口传播到用户设计代码中。 - MarkP
在上面的链接中,是否有可能从我的代码中定义的接口IFoo派生出“HelloWorldClass”类?因为据我了解,用户定义的代码位于不同的模块中,无法访问我的任何接口。 - MarkP
您提到以这种方式编译存在问题。如果我有许多源文件并逐个编译它们,那么会创建许多新的程序集还是只有一个大的程序集? - MarkP
会导致许多大型程序集。顺便说一下,我的代码允许在运行时定义接口的任何类型,因此它使用反射。 - Aliostad

1
如果我正确理解你想做的事情,我认为 CodeDom 和 this article 可以帮助你。这是你要找的吗?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接