2013-08-19 74 views
5

我试图调用动态LINQ select语句的功能,但即时得到错误:呼叫功能

No property or field 'A' exists in type 'Tuple2' 

示例代码:

void Main() 
{ 
    var a = new Tuple<int, int>(1,1); 
    var b = new[]{ a }; 
    var q = b.AsQueryable().Select("A.Test(it.Item1)"); 

    q.Dump(); 
} 

public static class A 
{ 
    public static int Test(int i) 
    { 
     return i++; 
    } 
} 

我应该如何改变我代码来得到这个工作?

如果我打电话内置函数Convert.ToInt32例如它工作正常。

var q = b.AsQueryable().Select("Convert.ToInt32(it.Item1)"); 

另外如何使用动态linq投射属性?

var q = b.AsQueryable().Select("((float)it.Item1)"); 
+0

在Enumerable.Select方法中使用字符串的语法是什么? –

+0

@Bob。写在标签中:dynamic-linq – xanatos

回答

8

,我会说,dynamic-linq不是“足够强大”做这些事情。它看起来只有在给定对象的方法和一些特殊类:MathConvert,各种基本类型(intfloatstring,...),GuidTimespanDateTime

这些类型的名单显然是如果您在文件上使用ilspy/reflector,则可见。他们在System.Linq.Dynamic.ExpressionParser.predefinedTypes

现在,显然我可能是错的,但这个工程:.Select("Guid.NewGuid().ToString()").Cast<string>().ToArray()

表明这是很可能的是“正确”的名单。

有文章在这里就如何修改动态LINQ如果你有兴趣http://www.krizzcode.com/2012/01/extending-dynamiclinq-language.html

现在,一个聪明的人会采取动态LINQ的来源,只是展开阵列......但这里也有不聪明的人......只有程序员需要但特别是内脏

var type = typeof(DynamicQueryable).Assembly.GetType("System.Linq.Dynamic.ExpressionParser"); 

FieldInfo field = type.GetField("predefinedTypes", BindingFlags.Static | BindingFlags.NonPublic); 

Type[] predefinedTypes = (Type[])field.GetValue(null); 

Array.Resize(ref predefinedTypes, predefinedTypes.Length + 1); 
predefinedTypes[predefinedTypes.Length - 1] = typeof(A); // Your type 

field.SetValue(null, predefinedTypes); 

做到这一点(你想要的类型)的第一次调用动态的LINQ(因为之后的第一个调用的方法/这些类型的属性会被缓存)

说明前:我们使用反射来补充我们的对象是这个“特殊列表”。

+0

而不是回答如果它可能是一个建议.... – andy

+1

@andy答案是不可能的是仍然是一个答案 – xanatos

+0

感谢指针@xanatos – Magnus

0
var b = new[]{ a }; 

以上阵列是不知道是什么类型的数组,并且它不是类型安全的?

你的价值观在变型数据类型分配,所以它不是整数值(我想字符串值),当你在查询这个值必须要convert.toint32(),因为你的类参数的数据类型为整数

请您尝试一下

var b = new **int**[]{ a }; 

,而不是var b = new[]{ a };

重要提示在这里(粗体):

No property or field 'xxx' exists in **type** 'xxx' 

并请看看本作之前的讨论:

Dynamic Linq - no property or field exists in type 'datarow'

0

我可能会混淆,但你的语法,让你使用一个字符串在Select s不编译我。以下语法的工作原理:

var q = b.AsQueryable().Select(it => A.Test(it.Item1)); 
+1

'您的选择无法为我编译,因为OP使用dynamic-linq http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part -1-using-the-linq-dynamic-query-library.aspx – I4V

+0

啊,所以我很困惑:) –

0

对我来说,以下工作:

var a = new Tuple<int, int>(1, 1); 
var b = new[] { a }; 
var q = b.AsQueryable().Select(it=>A.Test(it.Item1)); 
var q1 = b.AsQueryable().Select(it => Convert.ToInt32(it.Item1)); 
var q2 = b.AsQueryable().Select(it => (float) it.Item1); 
6

我知道已经有这个公认的答案,但它并没有为我工作。我正在使用Dynamic Linq 1.1.4。我想做这样的查询

$.GetNewestRisk() == null 

其中GetNewestRisk()是$表示的对象的公共方法。我一直得到这个错误“错误运行查询,'病人'类型的方法不可访问(在索引2)”。

我在源代码中发现有一个GlobalConfig对象,它允许分配一个自定义提供程序,该自定义提供程序将包含您可能要使用的所有类型。下面是自定义提供的源代码:

public class CustomTypeProvider: IDynamicLinkCustomTypeProvider 
{ 
    public HashSet<Type> GetCustomTypes() 
    { 
     HashSet<Type> types = new HashSet<Type>(); 
     types.Add(typeof(Patient)); 
     types.Add(typeof(RiskFactorResult)); 
     types.Add(typeof(PatientLabResult)); 
     types.Add(typeof(PatientVital)); 
     return types; 
    } 
} 

这里是我如何使用它:

System.Linq.Dynamic.GlobalConfig.CustomTypeProvider = new CustomType(); 

使这个电话后,我能够调用表达式里边的对象的方法。

+0

我能够使这个答案适应System.Linq.Dynamic.Core。它具有相同的界面,但它也有ParsingConfig,它允许您为单个表达式提供类型,而不是全局应用自定义类型。 – Kent