Mono 编译器即服务 (MCS)

Mono Compiler as a Service (MCS)(Mono 编译器即服务 (MCS))

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

问题描述

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

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(第一行)引发异常:

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:/下载 Mono.CSharp dll/tirania.org/blog/archive/2010/Apr-27.html 在 demo-repl.zip 文件中...并且不会引发异常...但是调用后的 out 参数(res)Evaluator.Evaluate 为空......所以我不确定出了什么问题.不抛出异常...

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 命名空间......虽然我不知道为什么......如果我只是 Evaluate "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; }

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

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

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

最后,在 ParseString 中,除非 AutoReset 为真,否则不要重置...

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 ();

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

本文标题为:Mono 编译器即服务 (MCS)