创建一个动态 Linq to EF 表达式,选择 IQueryable 到新类并分配属性。

4
我正在尝试动态创建等同于以下Linq的内容。
IQueryable<TypeOne> ones;
ones.Select(i => new TypeTwo { TwoProp = i.OneProp });

到目前为止,我有以下代码,但它还不完整。
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'

public class TwoTwo - 打错了吗? - markpsmith
是的,感谢您发现它。 - Joe
将其更改为 Expression.Lambda<Func<TypeOne, string>>(body, oneParam) - 但是您的表达式还有其他缺陷(它并不完全符合您要模拟的内容)。 - Rob
我正在尝试将TypeOne列表转换为TypeTwo列表,以有效地复制我的问题顶部的linq语句。如果我更改Expression.Lambda以使用字符串类型,则会返回字符串列表而不是TypeTwo列表。此外,它会给出“Block”类型的未知LINQ表达式异常。 - Joe
1个回答

4
你应该使用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表达式(即属性分配)。

非常感谢,这让我完全卡住了! - Joe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接