Как получить значение из анонимного выражения?

Для простоты представьте себе следующий код:

Я хочу создать Foo:

public class Foo
{
    public string Bar { get; set; }
}

И передайте его специальному методу Html Helper:

Html.SomeFunction(f => f.Bar);

Определяется как:

public string SomeFunction<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)

Я хочу получить значение Bar внутри этой функции, но понятия не имею, как ее получить.

Ответы

Ответ 1

Просто скомпилируйте выражение и получите значение.

Func<TModel, TValue> method = expression.Compile();

TValue value = method(html.ViewData.Model);
// might be a slightly different property, but you can get the ViewModel 
// from the HtmlHelper object. 

Ответ 2

Вам нужно будет вызвать Compile() в выражении, чтобы получить Func, а затем выполнить его.

public string SomeFunction<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
    TValue valueOfBar = expression.Compile()(html.Model); // Assumes Model is accessible from html.

    // Do stuff
}

Боковое примечание. Если нет необходимости в динамических выражениях или анализе выражения, вы можете также передать Func непосредственно.

Ответ 3

Для тех, кто использует выражение без MVT Model, можно получить имя и значение свойства следующим образом.

public static string Meth<T>(Expression<Func<T>> expression)
{
    var name = ((MemberExpression)expression.Body).Member.Name;
    var value = expression.Compile()();
    return string.Format("{0} - {1}", name, value);
}

использование:

Meth(() => YourObject.Property);

Ответ 4

Использование Compile() будет использовать структуру компилятора Roslyn и выпустить MSIL-код, который будет динамически загружен в ваше приложение. Этот исполняемый код занимает память, и в отличие от "нормальной" памяти он не подлежит сборке мусора, и вы не можете его самостоятельно освободить. Если вы делаете это слишком часто (например, регулярно во время генерации SQL), в конечном итоге у вас закончится нехватка памяти. Я столкнулся с этой проблемой и открыл свои решения в виде библиотеки с открытым исходным кодом:

https://www.nuget.org/packages/MiaPlaza.ExpressionUtils