将我的值类型转换为可空等价物

Zev*_*itz 5 c# linq dynamic-linq dynamic-linq-core

我有一个特别报告系统;我对查询的源类型或所需字段没有编译时知识。我可以在运行时使用System.Linq.Expressions.Expression工厂方法编写表达式树,并使用反射调用 LINQ 方法,但动态 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);
Run Code Online (Sandbox Code Playgroud)

动态 LINQ 支持显式转换:

// using static System.Linq.Dynamic.Core

var qry1 = range.Select("int?(it)");
Run Code Online (Sandbox Code Playgroud)

但在查询中只能引用一组特定的类型。如果我尝试Color在查询中使用:

var qry2 = range.Select("Color(it)");
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

“颜色”类型中不存在适用的方法“颜色”

如果我尝试显式转换为Color?

var qry3 = range.Select("Color?(it)");
Run Code Online (Sandbox Code Playgroud)

我得到:

未找到请求的值“颜色”。

如何使用动态 LINQ 库执行此操作?

Ste*_*ath 7

动态 LINQ 提供了Cast一种可以使用的方法,如下所示:

var range = Enumerable.Range(0,3).Select(x => (Color)x).AsQueryable();
var castDynamic = range.Cast(typeof(Color?)).ToDynamicArray();
castDynamic.Dump();
Run Code Online (Sandbox Code Playgroud)

您还可以传递带有输出类型名称的字符串。请注意,对于可为空的类型,您需要类型的全名:

string s = typeof(Color?).FullName;
s.Dump();
var castDynamicFromString = range.Cast(s);
castDynamicFromString.Dump();
Run Code Online (Sandbox Code Playgroud)

Cast也可以在动态 LINQ 字符串表达式中使用,可以将Type对象作为参数传入,也可以直接使用名称:

var castInSelect = range.Select($@"Cast(""{s}""").ToDynamicArray();
castInSelect.Dump();
Run Code Online (Sandbox Code Playgroud)

LINQPad 中的输出:

在此处输入图片说明