本文介绍了创建一个动态Linq to EF表达式以将IQueryable选择到新类中并分配属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试动态创建以下Linq的等效项.

I am trying to dynamically create the equivalent of the following Linq.

IQueryable<TypeOne> ones;
ones.Select(i => new TypeTwo { TwoProp = i.OneProp });

到目前为止,我有以下代码,但没有.

So far I have the following code but it isn't.

public class TypeOne
{
    public string OneProp { get; set; }
}

public class TypeTwo
{
    public string TwoProp { get; set; }
}

public static IQueryable<TypeTwo> Tester(IQueryable<TypeOne> data)
{
    ConstructorInfo constructor = typeof(TypeTwo ).GetConstructor(new Type[] { });
    Expression body = Expression.New(constructor);

    ParameterExpression oneParam = Expression.Parameter(typeof(TypeOne), "one");
    Expression prop1 = Expression.Property(oneParam, "OneProp");

    ParameterExpression twoParam = Expression.Parameter(typeof(TypeTwo ), "two");
    Expression prop2 = Expression.Property(twoParam, "TwoProp");

    Expression assign = Expression.Assign(prop2, prop1);
    body = Expression.Block(body, assign);

    return data.Select(Expression.Lambda<Func<TypeOne, TypeTwo >>(body, oneParam));
}

但是我遇到以下异常:

其他信息:类型'System.String'的表达式不能用于返回类型'TypeTwo'

Additional information: Expression of type 'System.String' cannot be used for return type 'TypeTwo'

推荐答案

您应使用 Expression.MemberInit 为此,例如:

public static IQueryable<TypeTwo> Tester(IQueryable<TypeOne> data)
{
    var source = Expression.Parameter(typeof(TypeOne), "source");
    var selector = Expression.Lambda<Func<TypeOne, TypeTwo>>(
        Expression.MemberInit(Expression.New(typeof(TypeTwo)),
            Expression.Bind(typeof(TypeTwo).GetProperty("TwoProp"), Expression.Property(source, "OneProp"))),
        source);
    return data.Select(selector);
}

您可以根据需要添加任意多个Expression.Bind表达式(即属性分配).

You can include as many Expression.Bind expressions (i.e. property assignments) as you want.

这篇关于创建一个动态Linq to EF表达式以将IQueryable选择到新类中并分配属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 11:22