gpt4 book ai didi

c# - 使用表达式生成 e => new { e.Id, e.CompanyId }

转载 作者:太空宇宙 更新时间:2023-11-03 13:20:07 27 4
gpt4 key购买 nike

这个问题是这个问题的延续 here .如果有人想知道为什么我需要做这样的事情,你可以在那个问题中找到理由。这并不重要,真的。

我需要这样的方法:

public virtual Expression<Func<T, object>> UpdateCriterion()
{
// this doesn't work because the compiler doesn't know if T has Id & CompanyId
return e => new { e.Id, e.CompanyId };
}

问题是,T 没有我可以用来从中提取 IdCompanyId 的父类(super class)型,我必须这样做它是动态的。感谢对那个引用问题的回答,我已经成功地为一个属性构建并使用了这种方法(e => e.Id),但是我在为两个属性实现它时遇到了问题。只是为了可见性,一个字段的解决方案是:

public virtual Expression<Func<T, object>> UpdateCriterion()
{
var param = Expression.Parameter(typeof(T));
var body = Expression.Convert(Expression.Property(param, "ID"), typeof(object));

return Expression.Lambda<Func<T, object>>(body, param);
}

我已经为这个问题烦恼了 6 个多小时...那么,我该如何解决这个问题?

最佳答案

这个 Lamba 的主体是一个 MemerInitExpression。

这是简单的部分。这里更大的问题是您在 Lambda 中使用匿名类型。

Expression<Func<TranslatedText, object>> exp;
exp = p => new { p.LanguageId, p.TextId};

如果您使用这样的 AnonymousType,编译器将检查您的代码,检测 AnonymousType 声明并即时创建这样的类型。

public class f__AnonymousType0
{
public int LanguageId { get; set; }
public int TextId { get; set; }
}

然后把你的 lambda 改成这样。

exp = p => new f__AnonymousType0 { LanguageId = p.LanguageId, TextId = p.TextId };

因为您想在运行时创建 lambda,所以 MemberInitExpression 所需的 f__AnonymousType0 类型不存在。

由于您需要一个实际类型来创建此表达式,因此您有两种选择。

1 - 编写一些泛型类,例如 .NET Framework 的 Tuple 类。对于核心,此解决方案仅限于最大数量的属性。

优点:易于创建和使用 – 缺点:属性数量有限。

public class KeyTuple<T1, T2>
{
public T1 Item1 { get; set; }
public T2 Item2 { get; set; }
}

public class KeyTuple<T1, T2, T3>
{
public T1 Item1 { get; set; }
public T2 Item2 { get; set; }
public T3 Item3 { get; set; }
}

public class KeyTuple<T1, T2, T3>
public class KeyTuple<T1, T2, T3, T4>
public class KeyTuple<T1, T2, T3, T4, T5>
public class KeyTuple<T1, T2, T3, T4, T5, T6>

2 - 您可以使用 Reflection.Emit 并在运行时创建一个类型 http://www.codeproject.com/Articles/121568/Dynamic-Type-Using-Reflection-Emit

优点:无限的属性数量 – 缺点:复杂

当你有一个类型时,你可以使用你已经知道的表达式树 api 来创建 lambda

var keys = new[] { "LanguageId", "TextId" };

var param = Expression.Parameter(typeof(TranslatedText));
var properties = keys.Select(p => Expression.Property(param, p)).ToList();

var keyTupleType = typeof(KeyTuple<,>).Assembly.GetType(string.Format("AnonymousTypeExpression.KeyTuple`{0}",keys.Count()));
keyTupleType = keyTupleType.MakeGenericType(properties.Select(p => p.Type).ToArray());

var bindings = properties.Select((p,i) => Expression.Bind(keyTupleType.GetProperty(string.Format("Item{0}",i + 1)),p)).ToArray();
var body = Expression.MemberInit(Expression.New(keyTupleType), bindings);
var result= Expression.Lambda<Func<TranslatedText, object>>(body, param);

这将创建一个看起来像这样的表达式

exp = p => new KeyTuple<int, int> { Item1 = p.LanguageId, Item2 = p.TextId };

关于c# - 使用表达式生成 e => new { e.Id, e.CompanyId },我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24631161/

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