Можно ли восстановить делегата из строки?c # .NET Core - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь создать пару программ на C # .NET Core, одна из которых генерирует «шаблоны» или «правила» в виде текста (XML, JSON и т. Д.), А другая переводит их в код, который будетзапустить.Это все еще на стадии технико-экономического обоснования, поэтому я открыт для любой рекомендации.Моя конкретная проблема касается восстановления делегатов:

Можно ли прочитать строку, например, "x => x [1]> 0", а затем преобразовать ее в делегат для использования в Linq?Например, можно:

string myRule = "x => x[1] >= 18";

каким-либо образом использовать в:

// for the example's sake, assume the following table has a fixed structure of "id, age" 
List<List<double>> myList = new List<List<double>>()
{
    new List<double>(){ 1, 25 },
    new List<double>(){ 2, 14 },
    new List<double>(){ 3, 30 }
};

int adults = myList.Count(StringToDelegate(myRule));
Console.WriteLine("Total adults " + adults);

Есть ли "StringToDelegate", который мог бы сделать эту работу?

Обратите внимание, что требуемый тип делегата (в данном случае «Func , bool>») заранее известен как программному обеспечению, которое создает строки, так и тому, которое должно их использовать.

Спасибо!

1 Ответ

0 голосов
/ 05 октября 2018

Благодаря первоначальному указателю от Амира Поповича я смог (через несколько часов) найти ответ.Поскольку это было не очень прямолинейно, я приведу здесь все детали для тех, кому это нужно в будущем (включая меня).

К сожалению, подход Roslyn (описанный здесь https://www.strathweb.com/2018/01/easy-way-to-create-a-c-lambda-expression-from-a-string-with-roslyn/),, хотя работает немедленноиз коробки, было очень медленным. Я испытал накладные расходы примерно 2600 мс для компиляции первого выражения и 100 мс для каждого выражения после этого. Однако в комментариях на этой странице один Йохен Кюнер указал на существование System.Linq.Dynamic.Пакет .Core (https://github.com/StefH/System.Linq.Dynamic.Core), который может выполнять ту же работу. Однако это не сработало из коробки, и даже примеры в документации приводили к ошибкам. После некоторых исследований я понял, что впакет, доступный в NuGet, и один Paritosh указал на необходимость также добавить более новую версию файла непосредственно в мой проект (см. Linq Dynamic ParseLambda не разрешает ).

Так что в основномчтобы заставить это работать (по крайней мере, в .NET Core) вам нужно:

1) Добавьте NuGet System.Linq.Dynamic.Core в свой проект.

2) Перейдите по следующей ссылке и получите CSharpSamples.zip от Microsoft:

https://msdn.microsoft.com/en-us/vstudio/bb894665.aspx?f=255&MSPPError=-2147217396

3) Найдите файл LinqSamples \ DynamicQuery \ DynamicQuery \ Dynamic.cs и скопируйте его в свой собственный проект.

С учетом вышесказанного у вас должна быть рабочая среда.Затем, если вы включите следующее:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Linq.Dynamic;

Вы можете написать код, подобный следующему:

List<List<double>> myList = new List<List<double>>()
{
    new List<double>(){ 1, 25 },
    new List<double>(){ 2, 14 },
    new List<double>(){ 3, 30 }
};

ParameterExpression[] x = new ParameterExpression[] { Expression.Parameter(typeof(List<double>), "x") };
Func<List<double>, bool> adultFilter = (Func<List<double>, bool>) System.Linq.Dynamic.DynamicExpression.ParseLambda(x, null, "x[1] > 18").Compile();
int adults = myList.Count(adultFilter);
Console.WriteLine("Total adults " + adults);

Обратите внимание, что существует класс DynamicExpression в обоих Linq.Expression и Link.Dynamic, следовательнонеобходимость предоставить полную ссылку и иметь дополнительную длинную линию.Также обратите внимание, что для компиляции и запуска вышеприведенного кода требуется около 30 мс, без дополнительных затрат на первое выражение.

Подробнее о том, как использовать библиотеку Linq.Dynamic, можно узнать здесь (хотя автор утверждает, что Wikiточна только на 80%):

https://github.com/StefH/System.Linq.Dynamic.Core/

Я надеюсь, что однажды пакет NuGet будет исправлен и Wiki будет улучшен, но до тех пор, возможно, эти заметки будутпомощь!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...