动态linq查询Xamarin.Mac中来自字符串的where子句

时间:2019-01-28 22:48:04

标签: c# linq xamarin.mac system.linq.dynamic

我正在尝试使用c#为Xamarin.Mac Cocoa项目实现简单的动态linq查询。

在WPF中,我可以使用System.Linq.Dynamic库从字符串创建动态linq查询,就像这样简单:

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

这是完成工作的一种快速而肮脏的方法,可以从UI传递过滤器字符串。

在Xamarin.Mac中,我无法添加System.Linq.Dynamic库,因此我一直在寻找与上述解决方案一样快的解决方案。

我尝试使用各种lambda解析器,但是还没有找到一个可行的解析器。这是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中,而linq中的查询无需借助表达式树即可动态构建查询?

0 个答案:

没有答案