gpt4 book ai didi

c# - 动态 LINQ : Specifying class name in new clause

转载 作者:行者123 更新时间:2023-11-30 12:33:39 27 4
gpt4 key购买 nike

使用 Dynamic LINQ,需要做哪些更改才能拥有给定类的字段?

例如,如何在 DLinq 中重现以下 C# 查询:

var carsPartial = cars.Select(c => new {c.year, c.name, make = new maker() {name = c.make.name} }).ToList();

我已应用此答案中提到的更改 https://stackoverflow.com/a/1468357/288747允许返回类型是调用类型而不是匿名类型。

类定义如下(如果有帮助的话):

class car
{
public int vid;
public int odo;
public int year;

public string name;

public maker make;
}

class maker
{
public string name;
public int firstYear;
}

以下不起作用(但我认为接近,但仍然不起作用,因为我没有对动态 linq 库进行必要的更改,而这正是我所需要的):

var carsPartial = cars.Select("new(name, year, new maker() {name = make.name})").ToList();

但它在 new maker() { 处失败(正如预期的那样)。

我确定我需要更改 DynamicLibrary.cs 才能使其正常工作,并且可以就如何更改它以实现此目的提供一些指导。

最佳答案

更新:我已经把我的答案变得更广泛了一点 blog post .

我还没有真正使用过 Dynamic Linq 库,但我查看了 DynamicLibrary.cs 代码以及另一个 stackoverflow question 中提供的支持生成类型类的更改。您在问题中提供了链接。对它们进行全部分析,似乎嵌套的 new-s 应该在您的配置中开箱即用。

但是,您的查询似乎不是正确的 Dynamic Linq 语言查询。请注意,DLinq 的查询字符串等同于 C#,它有自己的语法。

我相信查询应该读出以下内容:

var carsPartial = cars.Select("new(name, year, new maker(make.name as name) as make)").ToList();

编辑:

重读 this stackoverflow question更仔细地,我意识到,它实际上并没有扩展 Dynamic Linq 的语言以创建新的强类型类的可能性。他们只是将结果放入指定为 Select() 的通用参数的类,而不是在查询字符串中指定它。

要获得您需要的内容,您需要还原他们的更改(获取通用 DLinq)并应用我的更改,我刚刚验证可以工作:

找到ExpressionParser类的ParseNew方法,改成如下:

    Expression ParseNew() {
NextToken();

bool anonymous = true;
Type class_type = null;

if (token.id == TokenId.Identifier)
{
anonymous = false;
StringBuilder full_type_name = new StringBuilder(GetIdentifier());

NextToken();

while (token.id == TokenId.Dot)
{
NextToken();
ValidateToken(TokenId.Identifier, Res.IdentifierExpected);
full_type_name.Append(".");
full_type_name.Append(GetIdentifier());
NextToken();
}

class_type = Type.GetType(full_type_name.ToString(), false);
if (class_type == null)
throw ParseError(Res.TypeNotFound, full_type_name.ToString());
}

ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);
NextToken();
List<DynamicProperty> properties = new List<DynamicProperty>();
List<Expression> expressions = new List<Expression>();
while (true) {
int exprPos = token.pos;
Expression expr = ParseExpression();
string propName;
if (TokenIdentifierIs("as")) {
NextToken();
propName = GetIdentifier();
NextToken();
}
else {
MemberExpression me = expr as MemberExpression;
if (me == null) throw ParseError(exprPos, Res.MissingAsClause);
propName = me.Member.Name;
}
expressions.Add(expr);
properties.Add(new DynamicProperty(propName, expr.Type));
if (token.id != TokenId.Comma) break;
NextToken();
}
ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected);
NextToken();
Type type = anonymous ? DynamicExpression.CreateClass(properties) : class_type;
MemberBinding[] bindings = new MemberBinding[properties.Count];
for (int i = 0; i < bindings.Length; i++)
bindings[i] = Expression.Bind(type.GetProperty(properties[i].Name), expressions[i]);
return Expression.MemberInit(Expression.New(type), bindings);
}

然后,找到类 Res 并添加以下错误消息:

public const string TypeNotFound = "Type {0} not found";

Et voilà,您将能够构建如下查询:

var carsPartial = cars.Select("new(name, year, (new your_namespace.maker(make.name as name)) as make)").ToList();

确保包含完整的类型名称,包括整个命名空间+类路径。

为了解释我的更改,它只是检查 new 和左括号之间是否有一些标识符(请参阅开头添加的“if”)。如果是这样,我们解析完整的点分隔类名并尝试通过 Type.GetType 获取其 Type,而不是在匿名 new 的情况下构造自己的类>s.

关于c# - 动态 LINQ : Specifying class name in new clause,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8776248/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com