2012-11-18 118 views
5

我正在將基於Roslyn的腳本引擎嵌入到我的應用程序中,並開始面臨一些問題。當加載引用了我的引擎,我做了以下運行Roslyn腳本時未在運行時發現程序集

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

問題:

  1. 如果MyAssemblyLocation組件引用其他組件,我怎麼告訴羅斯林加載它們沒有做一個engine.AddReference("MyAssemblyLocation");
  2. 腳本應該運行的主機應用程序已經加載了一些我想在腳本中使用的程序集,有沒有辦法讓Roslyn將自己掛載到內存中已經加載的dll中,而不是加載新的實例?
  3. 最後,有沒有辦法告訴羅斯林遞歸加載的MyAssemblyLocation

謝謝所有的依賴。

回答

6

1)簡短的回答:您需要在腳本中將要使用的所有類型的組件上添加引用。

詳細信息: C#編譯器不會猜測依賴文件的位置。程序集文件不指定其所有依賴項的完整路徑。它只包含它們的名字,這通常不足以讓編譯器找到程序集文件。

更多詳細信息: 有兩種依賴關係。我將稱它們爲編譯時依賴關係(a)和運行時依賴關係(b)。 (a)假設程序集A.dll中的「public class A:B {}」,程序集B.dll中的「public class B {}」,並且腳本正在使用A,例如您創建了一個新的實例:「new A()」。在這種情況下,編譯器要求您添加對A.dll和B.dll的引用,因爲A派生自B,編譯器需要分析您使用的每種類型的繼承層次結構。因此,B.dll是腳本的編譯時依賴項 - 編譯器需要它才能正確分析腳本。 (b)考慮另一個例子:A.dll中的「公共類A {公共對象M(){返回新的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枚舉所有引用並加載它們中的每一個。

如果解釋不清楚或想了解更多詳細信息,請隨時提出進一步問題。

+0

優秀的答案,+1! – GETah