Моно-компилятор как услуга (MCS) - PullRequest
8 голосов
/ 04 августа 2010

Я бы хотел использовать компилятор 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, я полагаю.

Я попытался загрузить dll Mono.CSharp напрямую из http://tirania.org/blog/archive/2010/Apr-27.html в файле demo-repl.zip ... и это не вызывает исключения ... Однако параметр out (res) после вызова Evaluator.Evaluate равен нулю ... поэтому я не уверен, что происходитнеправильно.Никаких исключений не выдается ...

Итак, я хотел бы выяснить, почему dll, который я скачал с demo-repl.zip, возвращает ноль.

РЕДАКТИРОВАТЬ: я выяснил, почему он возвращает ноль.Кажется, по какой-то причине компилятор не захватывает пространство имен 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 действительно было возможным решением, яПотребуется изменить компилятор так, чтобы он генерировал одну динамическую сборку, вместо того, чтобы генерировать одну сборку на один вызов вычисления (в противном случае он вызывает серьезную утечку памяти, с которой я сталкивался ранее в форме CSharpCodeProvider).Кто-нибудь имеет представление о том, насколько это будет трудно, или кто-нибудь может указать мне правильное направление здесь?

Спасибо.

Ответы [ 2 ]

2 голосов
/ 05 августа 2010

Хорошо, думаю, у меня есть несколько ответов.

Чтобы решить проблему загрузки сборки, я могу либо вызвать вызов Assembly.LoadWithPartialName внутри Mono.CSharp.Driver.LoadAssembly, либо сделать следующее в моем приложении

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

Тогда ... убедитесь, что Reset вызывается хотя бы один раз в Init:

    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 ();
1 голос
/ 05 августа 2010

Согласно странице блога Мигеля, на которую вы ссылались, вы должны добавить ссылку на System.Core, чтобы использовать LINQ в .Net.

csharp> using System.Linq;
csharp> from x in "Foo" select x;
...