生成E =>新{e.Id,e.CompanyId}用防爆pressions [英] Generate e => new { e.Id, e.CompanyId } with Expressions

查看:117
本文介绍了生成E =>新{e.Id,e.CompanyId}用防爆pressions的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题是延续这个问题<一href="http://stackoverflow.com/questions/24575500/is-there-a-way-to-use-dynamic-in-lambda-ex$p$pssion-tree/">here.如果有人在乎知道我为什么要做这样的事情,你可以找到这个问题的理由。这不是问题,真的。

This question is a continuation of this question here. If someone cares to know why I need to do things like this, you can find the rationale in that question. Not that it matters, really.

我需要一个像这样的方法:

I need a method like this:

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 ,我可以用它来拉出编号 CompanyId 的,我必须动态地做到这一点。由于这个问题的答案引用的问题,我已经成功地构建和使用这种方法的一个属性( E =&GT; e.Id ),但我有问题是实现两个。只是为了知名度,一个领域的解决方案是:

The problem is, there is no supertype for T that I could use to pull out Id and CompanyId from, I have to do it dynamically. Thanks to the answer to that referenced question, I have successfully built and used this kind of method for one property (e => e.Id), but I'm having issues implementing it for two. Just for visibility, the solution for one field is:

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小时... ...那么,我该如何解决这个问题?

I've been going nuts with this for over 6 hours... So, how do I solve this?

推荐答案

这兰巴的身体是一个MemerInitEx pression。

The Body of this Lamba is a MemerInitExpression.

这是比较容易的部分。更大的问题是,你使用匿名类型在LAMBDA。

That was the easy part. The bigger Problem here is that you use an Anonymous Type in your Lambda.

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

如果你用这样的AnonymousType,编译器会检查你的code,检测AnonymousType声明,并会创建这样一个类型的飞行。

If you use such an AnonymousType, the Compiler will inspect your code, detect the AnonymousType declaration and will create a Type like this on the fly.

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

和改变你的lambda弄成这个样子。

And change your lambda into something like this.

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

由于您想创建拉姆达在运行时需要的MemberInitEx pression不存在f__AnonymousType0类型。

Because you would like to create the lambda at runtime the f__AnonymousType0 type you need for the MemberInitExpression does not exist.

当你需要一个实际的类型来创建此例pression你有两个选择来获得的。

As you need an actual Type to create this Expression you have two options to get one.

1 - 写一些通用类,如元组类的.NET Framework。芯的这种溶液被限制的属性的最大量。

1 - Write some generic classes like the Tuple class of the .NET Framework. Of cores this solution is limited to a maximum amount of properties.

亲:易于创建和使用 - CON:有限产权计数

pro: easy to create and use – con: limited property count.

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.$c$cproject.com /用品/ 121568 /动态型使用反射-的Emit

2 - You could use Reflection.Emit and create a type at runtime http://www.codeproject.com/Articles/121568/Dynamic-Type-Using-Reflection-Emit

亲:无限性计数 - CON:复杂

pro: unlimited property count – con: complicated

当你有,你可以使用防爆pression树API,您已经知道箱子一个类型的lambda

When you have a type you can use the Expression tree api you already know to crate the 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);

这将创建一个EX pression,看起来像这样

This creates an expression that looks like this

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

这篇关于生成E =&GT;新{e.Id,e.CompanyId}用防爆pressions的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆