从字符串列名称动态创建LINQ Select表达式

Sна*_*ƒаӽ 4 .net c# linq entity-framework

我有一个看起来像这样的方法:

public string GetColVal(string aAcctField, bool callM1, bool callM2)
{
    if (callM1)
    {
        // create select clause here to select a string column with name
        // equal to the value of aAcctField from Table1
        // Expression<Func<Table1, string>> selector = ?
        return M1(selector);
    }

    if (callM2)
    {
        // create select clause here to select a string column with name
        // equal to the value of aAcctField from Table2
        // Expression<Func<Table2, string>> selector = ?
        return M2(selector);
    }
}
Run Code Online (Sandbox Code Playgroud)

而且M1()是这样的:

public string M1(Expression<Func<Table1, string>> columnToSelect, string xType)
{
    // other logic 
    string acct = _cntx.Where(c => c.Type == xType)
                       .Select(columnToSelect)
                       .FirstOrDefault();
    return acct;
}
Run Code Online (Sandbox Code Playgroud)

M2()也是类似的东西.请注意,这些方法过于简化.而且方法M1()M2()工作完美.我可以这样调用它们:

// MyColumn is a strongly typed column in Table1
string acct = M1(x => x.MyColumn, "some value");
Run Code Online (Sandbox Code Playgroud)

但是,在方法内部GetColVal()我如何构造select子句?有关的评论selector将帮助您了解我打算做什么.所以,请继续阅读评论.

我试过这个:

public string GetColVal(string aAcctField, bool callM1, bool callM2)
{
    if (callM1)
    {
        // create select clause here to select a string column with name
        // equal to the value of aAcctField from Table1
        Expression<Func<Table1, string>> selector = (w) => w.GetType().GetProperty(aAcctField).Name;
        return M1(selector);
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

我得到了例外:

LINQ to Entities无法识别方法'System.Reflection.PropertyInfo GetProperty(System.String)'方法,并且此方法无法转换为存储表达式

我看过这些:

但它们都不是我需要的东西.

Iva*_*oev 10

基本上你需要使用Expression类方法一样Expression.Lambda,Expression.PropertyOrField等来样订做所需的选择:

static Expression<Func<T, TValue>> MemberSelector<T, TValue>(string name)
{
    var parameter = Expression.Parameter(typeof(T), "item");
    var body = Expression.PropertyOrField(parameter, name);
    return Expression.Lambda<Func<T, TValue>>(body, parameter);
}
Run Code Online (Sandbox Code Playgroud)

要支持嵌套属性,请将var body = ...行更改为

var body = name.Split('.').Aggregate((Expression)parameter, Expression.PropertyOrField);
Run Code Online (Sandbox Code Playgroud)

样品用法:

if (callM1)
{
    return M1(MemberSelector<Table1, string>(aAcctField));
}
...
Run Code Online (Sandbox Code Playgroud)