5

我正在将基于 Roslyn 的脚本引擎嵌入到我的应用程序中,并开始面临一些问题。将引用加载到我的引擎中时,我执行以下操作

var engine = new Roslyn.Scripting.CSharp.ScriptEngine();
engine.AddReference("MyAssemblyLocation");

问题:

  1. 如果MyAssemblyLocation程序集引用其他程序集,我如何告诉 Roslyn 加载它们而不执行engine.AddReference("MyAssemblyLocation");
  2. 应该运行脚本的主机应用程序已经加载了一些我想在脚本中使用的程序集,有没有办法让 Roslyn 将自己挂接到内存中已经加载的 dll 中而不加载新实例?
  3. 最后,有没有办法告诉 Roslyn 递归加载MyAssemblyLocation

谢谢你。

4

1 回答 1

6

1) 简短回答:您需要在脚本中要使用其类型的所有程序集上添加引用。

详细信息:C# 编译器不会猜测依赖文件的位置。程序集文件没有指定其所有依赖项的完整路径。它只包含它们的名称,这通常不足以让编译器能够找到汇编文件。

更多细节:有两种依赖关系。我将它们称为编译时依赖项 (a) 和运行时依赖项 (b)。

(a) 假设您在程序集 A.dll 中有“public class A : B {}”,在程序集 B.dll 中有“public class B {}”,并且您的脚本正在使用 A,假设您创建了一个新实例:“new一种()”。在这种情况下,编译器要求您添加对 A.dll 和 B.dll 的引用,因为 A 派生自 B,编译器需要分析您使用的每种类型的继承层次结构。因此 B.dll 是脚本的编译时依赖项 - 编译器需要它才能正确分析您的脚本。

(b) 考虑另一个例子:A.dll 中的“public class A { public object M() { return new B(); } }”和上面相同的 B.dll。现在在编译“new A().M()”时,编译器不需要知道 B,因为对 B 的引用只出现在方法 M 的主体中,编译器不分析导入方法的主体。在这种情况下,只需添加对 A.dll 的引用即可编译脚本。当脚本执行时,它调用方法 M。此时 CLR 加载程序集 B。这有点复杂,所以我将跳过详细信息,但在常见情况下,我们将能够为您找到程序集,所以您不需要t 需要显式添加引用。

2) 我建议使用带有 Assembly 对象的 AddReference 的重载。类似:engine.AddReference(typeof(SomeTypeInAssemblyFoo).Assembly) 加载包含 SomeTypeInAssemblyFoo 类型的程序集 Foo。

3)不是一个简单的。您可以使用 Reflection 或 Roslyn API 枚举所有引用并加载它们中的每一个。

如果解释不清楚或您想了解更多细节,请随时提出更多问题。

于 2012-11-19T19:30:05.303 回答