8

通常の .NET 3.5 アプリケーションから Mono のコンパイラをサービスとして利用したいと考えています。

最新のビット (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 が csc.exe ではなく Mono.exe を使用してコンパイルされたためだと思います。

http://tirania.org/blog/archive/2010/Apr-27.htmlから直接 Mono.CSharp dll をdemo-repl.zip ファイルにダウンロードしようとしましたが、例外はスローされません。 ..ただし、Evaluator.Evaluate を呼び出した後の out パラメータ (res) は null です...そのため、何が問題なのかわかりません。例外はスローされません...

では、demo-repl.zip からダウンロードした dll が null を返す理由を突き止めたいと思います。

編集: null を返す理由がわかりました。何らかの理由でコンパイラが System.Linq 名前空間を取得していないようです...理由はわかりませんが... "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 を実際に実行可能なソリューションにするためには、評価呼び出しごとに 1 つのアセンブリを発行するのではなく、1 つの動的アセンブリに発行するようにコンパイラを変更する必要があります (そうしないと、重大なメモリ リークが発生し、以前に CSharpCodeProvider の形で扱ったことがあります)。これがどれほど難しいか、誰かが私を正しい方向に向けることができますか?

ありがとう。

4

2 に答える 2

2

わかりました、私はいくつかの答えがあると思います。

アセンブリの読み込みの問題を解決するには、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で少なくとも1回呼び出されることを確認します。

    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 ();
于 2010-08-04T21:19:56.677 に答える
1

リンクしたMiguelのブログページによると、.NetでLINQを使用するには、System.Coreへの参照を追加する必要があります。

csharp> using System.Linq;
csharp> from x in "Foo" select x;
于 2010-08-04T20:51:51.290 に答える