Динамический запрос linq, где предложение из строки с Xamarin.Mac - PullRequest
0 голосов
/ 29 января 2019

Я пытаюсь реализовать простой динамический запрос linq для проекта Xamarin.Mac Cocoa с использованием c #.

В WPF я мог бы использовать библиотеку System.Linq.Dynamic для создания динамических запросов linq из строкис чем-то таким простым:

string filter = "type == /"Person"/ && last_name == /"Smith"/";
List<Contact> contacts = ContactList.Where(filter);

Это был быстрый и грязный способ выполнить работу, строки фильтра можно было передать из пользовательского интерфейса.

В Xamarin.Mac IЯ не могу добавить библиотеку System.Linq.Dynamic, поэтому я застрял в поиске решения так же быстро, как и выше.

Я пытался использовать различные лямбда-парсеры, но не нашел такого, которыйсработало еще.Вот пример синтаксического анализатора Microsoft.CodeAnalysis.CSharp.Scripting, но я недостаточно опытен, чтобы знать, как это реализовать:

private async Task<List<Contact>> QueryContacts()
    {
        try
        {
            var contactFilter = search.searchstring;
            var lambdaParser = new LambdaParser();
            var context = new Dictionary<string, object>();
            context["contact"] = (Func<Contact>)(() => new Contact());
            return App.ContactList.Where(lambdaParser.Eval(contactFilter, context));
        }
        catch (Exception ex)
        {
            Err(ex, "QueryContacts");
        }
        return App.ContactList;
    }

Вот еще один, который я пробовал:

private async Task<List<Contact>> QueryContacts()
    {
        try
        {
            string query = search.searchstring;
            var externals = new Dictionary<string, object>();
            externals.Add("Contacts", App.ContactList.AsQueryable());
            var expression = DynamicExpression.Parse(typeof(IQueryable<Contact>), query, new[] { externals });
            var result = App.ContactList.AsQueryable().Provider.CreateQuery(expression);
            return (List<Contact>)result;

        }
        catch (Exception ex)
        {
            Err(ex, "QueryContacts");
        }
        return App.ContactList;
    }

А вот последний, который я пробовал.Кажется, этот пример близок, но я получаю исключение «Количество указанных параметров не соответствует ожидаемому числу»:

private async Task<List<Contact>> QueryContacts()
    {
        try
        {
            string query = search.searchstring; // "id == 1"
            var p = Expression.Parameter(typeof(Contact), "Contact");
            var e = System.Linq.Dynamic.DynamicExpression.ParseLambda<Contact, bool>(query, new[] { p });
            var result = e.Compile().DynamicInvoke(App.ContactList.ToArray());
            return (List<Contact>)result;

        }
        catch (Exception ex)
        {
            Err(ex, "QueryContacts");
        }
        return App.ContactList;
    }

Значение search.searchstring в этом случае было простым: id == 1. В этой строке выдается исключение:

var result = e.Compile().DynamicInvoke(App.ContactList.ToArray());

Вот трассировка стека для исключения на случай, если это будет полезно:

    at System.Reflection.MonoMethod.ConvertValues (System.Reflection.Binder binder, System.Object[] args, System.Reflection.ParameterInfo[] pinfo, System.Globalization.CultureInfo culture, System.Reflection.BindingFlags invokeAttr) [0x00016] in /Library/Frameworks/Xamarin.Mac.framework/Versions/4.4.1.193/src/Xamarin.Mac/mcs/class/corlib/System.Reflection/MonoMethod.cs:331 
  at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00011] in /Library/Frameworks/Xamarin.Mac.framework/Versions/4.4.1.193/src/Xamarin.Mac/mcs/class/corlib/System.Reflection/MonoMethod.cs:293 
  at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in /Library/Frameworks/Xamarin.Mac.framework/Versions/4.4.1.193/src/Xamarin.Mac/mcs/class/referencesource/mscorlib/system/reflection/methodbase.cs:229 
  at System.Delegate.DynamicInvokeImpl (System.Object[] args) [0x000e1] in /Library/Frameworks/Xamarin.Mac.framework/Versions/4.4.1.193/src/Xamarin.Mac/mcs/class/corlib/System/Delegate.cs:461 
  at System.MulticastDelegate.DynamicInvokeImpl (System.Object[] args) [0x00008] in /Library/Frameworks/Xamarin.Mac.framework/Versions/4.4.1.193/src/Xamarin.Mac/mcs/class/corlib/System/MulticastDelegate.cs:67 
  at System.Delegate.DynamicInvoke (System.Object[] args) [0x00000] in /Library/Frameworks/Xamarin.Mac.framework/Versions/4.4.1.193/src/Xamarin.Mac/mcs/class/corlib/System/Delegate.cs:406 
  at WealthBoxAddon.ViewController+<QueryContacts>d__95.MoveNext () [0x00059] in /Users/chrisbrowning/Projects/WealthBoxAddon/WealthBoxAddon/ViewController.cs:548 

Хуже того, я мог бы использовать деревья выражений, но есть много кода с ними и не так легко отладить.

Есть ли решение, которое может взять строку и использовать ее в linq, где запрос для динамического построения запросов без обращения к деревьям выражений?

...