[英]Mono Compiler as a Service (MCS)
我想將Mono的編譯器作為我的常規.NET 3.5應用程序中的一項服務使用。
我下載了最新版本(2.6.7),在Visual Studio中創建了一個簡單的控制台應用程序,並引用了Mono.CSharp dll。
然后,在我的控制台應用程序中(直接在線獲取示例):
Evaluator.Run("using System; using System.Linq;");
bool ress;
object res;
Evaluator.Evaluate(
"from x in System.IO.Directory.GetFiles (\"C:\\\") select x;",
out res, out ress);
foreach (var v in (IEnumerable)res)
{
Console.Write(v);
Console.Write(' ');
}
這會在Evaluator.Run(第一行)處引發異常:
Illegal enum value: 2049.
Parameter name: access
我相信這是因為dll是使用Mono.exe而不是csc.exe編譯的。
我嘗試直接從demo-repl.zip文件中的http://tirania.org/blog/archive/2010/Apr-27.html下載Mono.CSharp dll ...這不會引發異常。 ..但是,調用Evaluator.Evaluate之后的out參數(res)為null ...所以我不確定出了什么問題。 沒有異常被拋出...
因此,我想弄清楚為什么我從demo-repl.zip下載的dll返回null。
編輯:我想通了為什么它返回null。 似乎出於某種原因,編譯器沒有選擇System.Linq命名空間...雖然我無法告訴原因...如果我只是評估“ System.IO.Directory.GetFiles(\\” C:\\\\ “)”,效果很好。
更新:絕對似乎Mono編譯器選擇了引用的System程序集存在問題。 如果我直接復制其csharp控制台工具的示例:
csharp> var list = new int [] {1,2,3};
csharp> var b = from x in list
> where x > 1
> select x;
csharp> b;
我得到例外:
{interactive}(1,25): error CS1935: An implementation of `Select' query expressio
n pattern could not be found. Are you missing `System.Linq' using directive or `
System.Core.dll' assembly reference?
另外,為了使MCS實際上是一個可行的解決方案,我需要修改編譯器,以便將其發出給單個動態程序集,而不是每個評估調用都發出一個程序集(否則,它將產生大量的內存泄漏,這將導致大量內存泄漏)我以前以CSharpCodeProvider的形式進行過處理。 有誰知道這將有多困難,或者有人可以在這里向我指出正確的方向?
謝謝。
好吧,我想我有一些答案。
要解決程序集加載問題,我可以在Mono.CSharp.Driver.LoadAssembly中調用Assembly.LoadWithPartialName,或者在我的應用程序中執行以下操作
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
private static bool isResolving;
static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
if (!isResolving)
{
isResolving = true;
var a = Assembly.LoadWithPartialName(args.Name);
isResolving = false;
return a;
}
return null;
}
為了使Mono在每個Evaluate / Compile調用中重用相同的動態程序集,我要做的就是以下更改(盡管我可能在這里缺少復雜性).....
在Mono.CSharp.Evaluator中,我添加了屬性:
/// <summary>
/// Gets or sets a value indicating whether to auto reset when evaluations are performed and create a new assembly.
/// </summary>
/// <value><c>true</c> if [auto reset]; otherwise, <c>false</c>.</value>
public static bool AutoReset { get; set; }
然后...確保在Init中至少調用一次Reset:
static void Init ()
{
Init (new string [0]);
Reset();
}
最后,在ParseString中,除非AutoReset為true,否則不要重置...
static CSharpParser ParseString (ParseMode mode, string input, out bool partial_input)
{
.
.
.
if (AutoReset) Reset ();
根據您鏈接的Miguel的博客頁面,您必須添加對System.Core的引用,才能在.Net上使用LINQ。
csharp> using System.Linq;
csharp> from x in "Foo" select x;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.