Roslyn/CSharpScript - 如何保存/加载编译以避免编译等待时间

7
我正在尝试将C#脚本集成到我的数据库应用程序中。我使用“globals”对象使全局变量可以从脚本中访问。
如果脚本首次编译,我对等待时间不满意。如何保存和加载编译以避免等待时间?
Script<object> script = CSharpScript.Create(scriptCode, globalsType: typeof(MyGlobals));
script.Compile();   //<-- load the Compilation from database/file here
script.RunAsync(myGlobalsInstance).Wait();

你应该编译一个普通的汇编而不是脚本。 - SLaks
如何手动创建编译的信息可以在这里找到:链接 - m0sa
2个回答

4
您可以创建一个CSharpScript,然后通过GetCompilation获取编译以获得编译。
var script = CSharpScript.Create("script..");
var compilation = script.GetCompilation();

从编译中,您实际上可以将dll和pdb compilation.Emit() 到磁盘或内存中。麻烦的是(以及roslyn内部的一点),如何在您拥有程序集后获取代码的委托以执行。您可以在此处查看roslyn如何执行此操作


2
如果您拥有程序集(.dll),为什么还需要CSharpScript呢?您只需通过装载程序集(Assembly.Load)来创建类型(Activator.CreateType),并创建要执行的委托即可。 - m0sa
据我所知,C#脚本没有入口点,在我的情况下,它应该直接访问“全局”变量的成员。也就是说,我想从流中重新加载它,但我不知道该怎么做。 - Bogomil
一个C#脚本没有任何类可以实例化,也没有可执行的方法 - 这就是我的问题。 - Bogomil
@Bogomil,您能否提供一个示例脚本,以便我们知道您在谈论什么? - m0sa
2
我在这里找到了一个解决方案。 - Bogomil
显示剩余2条评论

-1

如果您想要进行预编译,可以使用 System.CodeDom.Compiler 中的类;

CompilerParameters opts = new CompilerParameters();

opts.OutputAssembly = <Destination FileName>;
opts.ReferencedAssemblies.AddRange(<needed references>);
//set other options;            

var codeProvider = new Microsoft.CSharp.CSharpCodeProvider();
var results = codeProvider.CompileAssemblyFromFile(opts, <Your script source files>);
//check that there's no errors in the results.Errors

现在你在磁盘上有一个已编译的程序集。你可以动态加载它,实例化其中的类并执行方法。你应该设计脚本中运行的代码,使其能够接受一些配置。你应该采取以下步骤:

var mydll =  AppDomain.CurrentDomain.Load(<compiled Assembly From the previous step>);
    var classInstance =  <YouTypeOrInterface>mydll.CreateInstance(
      <TypeFromTheAssembly>, 
      false, 
      BindingFlags.CreateInstance, 
      null,                                                                
      new object[] { <Arguments you need to provides to your class constructor> },                                                                              CultureInfo.InvariantCulture, null);

现在你可以对这个实例做任何想做的事情。例如:classInstance.ExecuteSomething(...)


1
请注意,C#脚本与普通的C#不同,因此尝试使用CodeDOM编译脚本可能不起作用,并且需要更改脚本。另外,如果您这样做,我认为没有理由使用CodeDOM而不是Roslyn,后者也可以编译程序集。 - svick

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