Я хотел бы использовать компилятор Mono как услуга от моей регулярной.NET 3,5 приложения.
Я загрузил последние биты (2.6.7), создал простое консольное приложение в Visual Studio и сослался на Моно. До-диез 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. Выполненный (первая строка):
Illegal enum value: 2049.
Parameter name: access
Это вызвано тем, что dll был скомпилирован с помощью Mono.exe, не csc.exe, я верю.
Я попытался загрузить Моно. До-диез dll непосредственно из http://tirania.org/blog/archive/2010/Apr-27.html в файле demo-repl.zip... и это не выдает исключение... Однако параметр (res) после называния Средства анализа. Оцените является пустым..., таким образом, я не уверен, что идет не так, как надо. Никакое исключение не выдается...
Так, я хотел бы выяснить, почему dll я загрузил с пустого указателя возвратов demo-repl.zip.
Править: Я выяснил, почему это возвращает пустой указатель. Кажется по некоторым причинам, что компилятор не берет Систему. Пространство имен Linq..., хотя я не могу сказать почему... Если я просто Оцениваю "Систему. IO.Directory. GetFiles (\"C:\\")", это хорошо работает.
ОБНОВЛЕНИЕ: определенно кажется, что существует что-то не так с Моно компилятором, берущим Системные блоки, на которые ссылаются. Если я непосредственно копирую образец их консольного инструмента до-диеза:
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). У кого-либо есть идея того, насколько трудный это будет, или кто-либо может указать на меня в правильном направлении здесь?
Спасибо.
Хорошо, думаю, у меня есть несколько ответов.
Чтобы решить проблему с загрузкой сборки, я могу либо вызвать 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 / Вызов компиляции, все, что мне нужно было изменить, это следующее (хотя, вероятно, мне здесь не хватает некоторых сложностей) .....
Внутри 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 не истинно ...
static CSharpParser ParseString (ParseMode mode, string input, out bool partial_input)
{
.
.
.
if (AutoReset) Reset ();
Согласно странице блога Мигеля, которую вы связали, вы должны добавить ссылку на System.Core, чтобы использовать LINQ в .Net.
csharp> using System.Linq;
csharp> from x in "Foo" select x;