我想使用Mono的编译器作为我的常规.NET 3.5应用程序的一项服务。
我已经下载了最新的bits (2.6.7),在Visual Studio中创建了一个简单的控制台应用程序,并引用了Mono.CSharp动态链接库。
然后,在我的控制台应用程序中(直接从在线示例中提取):
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 file...and中直接从http://tirania.org/blog/archive/2010/Apr-27.html下载Mono.CSharp dll,它在调用Evaluator.Evaluate is null...so之后没有抛出输出参数(res),我不确定出了什么问题。没有抛出异常...
所以,我想弄清楚为什么我从demo-repl.zip下载的dll返回null。
编辑:我知道为什么它返回null了。似乎由于某种原因,编译器没有提取System.Linq namespace...though我不能告诉why...If我只是计算"System.IO.Directory.GetFiles (\"C:\")",它工作得很好。
更新: Mono编译器拾取引用的系统程序集肯定有问题。如果我直接复制他们的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成为实际可行的解决方案,我需要修改编译器,使其发出单个动态程序集,而不是每次evaluate调用发出一个程序集(否则它会出现严重的内存泄漏,我以前以CSharpCodeProvider的形式处理过这个问题)。有人知道这有多难吗,或者有人能给我指出正确的方向吗?
谢谢。
发布于 2010-08-05 05:19:57
好的,我想我有一些答案。
要解决程序集加载问题,我可以在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在每次评估/编译调用时重用相同的动态程序集,我需要做的更改如下(尽管这里可能会遗漏一些复杂的东西).....
在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; }Then...make sure Reset在Init中至少调用一次:
static void Init ()
{
Init (new string [0]);
Reset();
}最后,在ParseString中,除非AutoReset为真,否则不要重置...
static CSharpParser ParseString (ParseMode mode, string input, out bool partial_input)
{
.
.
.
if (AutoReset) Reset ();发布于 2010-08-05 04:51:51
根据你所链接的米格尔的博客页面,为了在.Net上使用System.Core,你必须添加一个对LINQ的引用。
csharp> using System.Linq;
csharp> from x in "Foo" select x;https://stackoverflow.com/questions/3407318
复制相似问题