单编译器即服务(MCS) [英] Mono Compiler as a Service (MCS)

查看:244
本文介绍了单编译器即服务(MCS)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从我的常规.NET 3.5应用程序中使用Mono的编译器作为服务。

I'd like to consume Mono's compiler as a service from my regular .NET 3.5 application.

我已经下载最新的位(2.6.7)在Visual Studio中创建了一个简单的控制台应用程序并引用了Mono.CSharp dll。

I've downloaded the latest bits (2.6.7), created a simple console application in Visual Studio and referenced the Mono.CSharp dll.

然后,在我的控制台应用程序

Then, in my console app (straight out of a sample online):

    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(第一行) p>

This throws an exception at Evaluator.Run (the first line):

Illegal enum value: 2049.
Parameter name: access

这是因为dll是使用Mono.exe而不是csc.exe编译的。

This is because the dll was compiled using Mono.exe, not csc.exe, I believe.

我试图直接从 http:// tirania下载Mono.CSharp dll。 org / blog / archive / 2010 / Apr-27.html 在demo-repl.zip文件...并且不会抛出异常...但是out参数(res)调用Evaluator.Evaluate是null ...所以我不知道发生了什么问题。没有异常被抛出...

I've tried downloading the Mono.CSharp dll directly from http://tirania.org/blog/archive/2010/Apr-27.html in the demo-repl.zip file...and that does not throw an exception...However the out parameter (res) after calling Evaluator.Evaluate is null...so I'm not sure what's going wrong. No exception is thrown...

所以,我想知道为什么我从demo-repl.zip下载的dll返回null。

So, I'd like to figure out why the dll I downloaded from the demo-repl.zip returns null.

编辑:我想出了为什么它返回null。看起来像是由于某种原因,编译器没有拾起System.Linq命名空间...虽然我不能告诉为什么...如果我只是评估System.IO.Directory.GetFiles(\C:\\ \\\),它工作正常。

I figured out why it returns null. It seems like for some reason the compiler isn't picking up the System.Linq namespace...though I can't tell why...If I just Evaluate "System.IO.Directory.GetFiles (\"C:\\")", it works fine.

更新:看起来似乎Mono编译器拾取引用的系统程序集有什么问题。如果我直接复制他们的csharp控制台工具的示例:

UPDATE: It definitely seems like there's something wrong with the Mono compiler picking up referenced System assemblies. If I directly copy the sample of their csharp console tool:

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的形式)。有没有人知道这将是多么困难,或任何人可以指向我在这里正确的方向?

Also, in order for the MCS to actually be a feasible solution, I'll need to modify the compiler so that it emits to one single dynamic assembly, instead of emitting one assembly per evaluate call (otherwise it presents a major memory leak, which I've dealt with before in the form of the CSharpCodeProvider). Does anyone have an idea of how difficult this will be or can anyone point me in the right direction here?

谢谢。

推荐答案

好的,我想我有一些答案。

Ok, I think I have some answers.

为了解决组件加载问题,调用Mono.CSharp.Driver.LoadAssembly内部的Assembly.LoadWithPartialName,或在我的应用程序中执行以下操作

To resolve the assembly load problem, I can either place a call to Assembly.LoadWithPartialName inside Mono.CSharp.Driver.LoadAssembly, or do the following in my application

        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调用重复使用相同的动态装配,我不得不改变是以下(虽然可能有复杂性我在这里失踪).....

To make Mono reuse the same dynamic assembly for each Evaluate/Compile call, all I had to change is the following (although there are probably complexities I'm missing here).....

在Mono.CSharp.Evaluator里面,我添加了属性:

Inside Mono.CSharp.Evaluator, I added the property:

/// <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; }

然后...确保Reset在Init中至少调用一次:

Then...make sure Reset is called at least once in Init:

    static void Init ()
    {
        Init (new string [0]);
        Reset();
    }

最后,在ParseString中,除非AutoReset为true否则不要复位。

And finally, in ParseString, simply don't reset unless AutoReset is true...

        static CSharpParser ParseString (ParseMode mode, string input, out bool partial_input)
        {
.
.
.
            if (AutoReset) Reset ();

这篇关于单编译器即服务(MCS)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆