动态linq中的调用函数

我试图在动态linq select语句中调用一个函数,但我得到错误:

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

示例代码:

 void Main() { var a = new Tuple(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)"); 

我会说dynamic-linq不够“强大”来做这些事情。 它仅在给定对象和一些特殊类中查找方法: MathConvert ,各种基类型( intfloatstring ,…), GuidTimespanDateTime

如果在文件上使用ilspy / reflector,则可清楚地看到这些类型的列表。 它们位于System.Linq.Dynamic.ExpressionParser.predefinedTypes

现在,显然我可能是错的,但这有效: .Select("Guid.NewGuid().ToString()").Cast().ToArray()

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

如果你有兴趣,这里有一篇关于如何修改动态LINQ的文章http://www.krizzcode.com/2012/01/extending-dynamiclinq-language.html

现在,一个聪明的人将采取动态linq的来源,只是扩展该arrays……但这里没有聪明的人…只有程序员需要血,但特别是内脏

 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); 

在第一次调用Dynamic Linq之前执行此操作(使用您需要的类型)(因为在第一次调用之后,这些类型的方法/属性被缓存)

说明:我们使用reflection将我们的对象添加到此“特殊列表”中。

我知道已经有一个已接受的答案,但它对我不起作用。 我正在使用Dynamic Linq 1.1.4。 我想做这样的查询

 $.GetNewestRisk() == null 

其中GetNewestRisk()是$表示的对象上的公共方法。 我一直收到此错误“运行查询时出错,类型’患者’的方法无法访问(在索引2处)”。

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

 public class CustomTypeProvider: IDynamicLinkCustomTypeProvider { public HashSet GetCustomTypes() { HashSet types = new HashSet(); 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(); 

进行此调用后,我可以在表达式内的对象上调用方法。

@xanatos答案不适用于.Net Core版本。 所以我在System.Dynamic.Linq.Core上发现了@Kent类似的相关内容,测试了图书馆作者自己编写的DynamicExpressionParserTests 。

给定的TestCustomTypeProvider类允许您使用DynamicLinqType类注释,这对此问题非常有用。

要回答问题,您只需要定义类(确保使用DynamicLinqType进行批注):

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

如上所述添加customTypeProvider:

 private class TestCustomTypeProvider : AbstractDynamicLinqCustomTypeProvider, IDynamicLinkCustomTypeProvider { private HashSet _customTypes; public virtual HashSet GetCustomTypes() { if (_customTypes != null) { return _customTypes; } _customTypes = new HashSet(FindTypesMarkedWithDynamicLinqTypeAttribute(new[] { GetType().GetTypeInfo().Assembly })); return _customTypes; } } 

并使用带有可配置选择的ParsingConfig来调用它:

 var config = new ParsingConfig { CustomTypeProvider = new TestCustomTypeProvider() }; var q = b.AsQueryable().Select(config, "A.Test(it.Item1)"); 

我可能会感到困惑,但是你在Select中使用字符串的语法不能为我编译。 以下语法有效:

 var q = b.AsQueryable().Select(it => A.Test(it.Item1)); 
 var b = new[]{ a }; 

上面的数组是不知道什么类型的数组,它不是类型安全的?

您的值以变量数据类型分配,因此它不是整数值(我认为字符串值),当您在查询中获取此值时,必须转换为.toint32(),因为您的类参数数据类型是整数

请试一试

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

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

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

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

请查看以前的讨论:

动态Linq – “datarow”类型中不存在任何属性或字段

以下为我工作:

 var a = new Tuple(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); 

@Armand为这个问题提出了一个出色的解决方案,并且是我能够找到的唯一解决方案,我希望为尝试相同方法的任何人添加它。

标有……的类

 [DynamicLinqType] 

…运行以下行时必须考虑到:

 FindTypesMarkedWithDynamicLinqTypeAttribute(new[] { GetType().GetTypeInfo().Assembly }) 

在上面提供的解决方案中,这假定包含要评估的函数的类与代码当前所在的同一类。如果要在所述类之外使用这些方法,则程序集将需要更改。

 FindTypesMarkedWithDynamicLinqTypeAttribute(new[] { typeof(AnotherClassName).Assembly }) 

上述解决方案没有任何变化,这只是为了解释任何试图使用它的人。