我有一个临时报告系统;我没有查询源类型或必填字段的编译时知识。我可以在运行时使用System.Linq.Expressions.Expression
工厂方法来编写表达式树,并使用反射来调用LINQ方法,但是Dynamic LINQ是一个更简单的解决方案。
报告系统应允许返回LEFT JOIN结果的查询。连接表中的字段在数据库中为NOT NULL
。但是由于这是LEFT JOIN
,因此对于某些记录,这些字段将包含NULL
。 EF6生成的表达式依赖于此,因为该表达式投影为不可为空的值类型。
如果我是在编译时LINQ上执行此操作,则将显式转换为可空类型:
enum Color { Red, Green, Blue }
// using System;
// using static System.Linq.Enumerable;
// using System.Linq;
var range = Range(0, 3).Select(x => (Color)x).AsQueryable();
var qry = range.Select(x => (Color?)x);
动态LINQ支持显式转换:
// using static System.Linq.Dynamic.Core
var qry1 = range.Select("int?(it)");
,但查询中只能引用specific set of types。如果我尝试在查询中使用Color
:
var qry2 = range.Select("Color(it)");
我收到以下错误:
“颜色”类型中不存在适用的方法“颜色”
,如果我尝试显式转换为Color?
:
var qry3 = range.Select("Color?(it)");
我得到:
未找到所需的值'Color'。
如何使用Dynamic LINQ库执行此操作?
答案 0 :(得分:7)
动态LINQ提供了一种Cast
方法,该方法可以按如下方式使用:
var range = Enumerable.Range(0,3).Select(x => (Color)x).AsQueryable();
var castDynamic = range.Cast(typeof(Color?)).ToDynamicArray();
castDynamic.Dump();
您还可以传递带有输出类型名称的字符串。请注意,对于可为空的类型,您需要该类型的全名:
string s = typeof(Color?).FullName;
s.Dump();
var castDynamicFromString = range.Cast(s);
castDynamicFromString.Dump();
Cast
也可以在Dynamic LINQ字符串表达式中使用,可以将Type
对象作为参数传递,也可以直接使用名称:
var castInSelect = range.Select($@"Cast(""{s}""").ToDynamicArray();
castInSelect.Dump();
在LINQPad中输出:
答案 1 :(得分:3)
尝试一下:
var arg0 = Expression.Parameter(typeof(Color), "x");
var expr = DynamicExpressionParser.ParseLambda(new[] { arg0 }, typeof(Color?), "x");
var qry2 = range.AsQueryable().Select("@0(it)", expr);
另请参见https://github.com/StefH/System.Linq.Dynamic.Core/wiki/Dynamic-Expressions#dynamic-lambda-invocation
答案 2 :(得分:0)
我建议您可以使用以下代码段来识别输入数字是否为枚举的一部分。
public static bool IsValuePresent<T>(int number) where T : Enum
{
return !Enum.GetValues(typeof(T)).Cast<int>().Contains(number);
}
以下可能是用于检查枚举中是否存在输入值的调用
EnumerationConverter.IsValuePresent<Color>(99); //returns False
EnumerationConverter.IsValuePresent<Color>(2); //returns True
在上述语句中获得False后,我们可以将其值设置为null,否则就可以像下面给出的代码一样,执行从整数到枚举的简单泛型类型转换器。
public static T GetAsEnum<T>(int number) where T : Enum
{
if (Enum.IsDefined(typeof(T), number))
{
return (T)Enum.ToObject(typeof(T), number);
}
return default(T);
}
基于您必须检查有效的枚举值然后进行转换的理解,可以尝试上述解决方案,如果有任何其他方面,请在此处发布以进行更新。