在ASP.NET Core 3.0中替代ExpressionHelper?

时间:2019-09-06 12:06:33

标签: c# asp.net-core-3.0

在ASP.NET Core 2.x中,我使用了GetExpressionText类的ExpressionHelper类的静态方法IHtmlHelper<T>作为扩展方法:

using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;

public static class HtmlHelperExtensions
{
    public static string GetExpressionText<TModel, TResult>(
        this IHtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TResult>> expression)
    {
        return ExpressionHelper.GetExpressionText(expression);
    }
}

在ASP.NET Core 3.0名称空间Microsoft.AspNetCore.Mvc.ViewFeatures.Internal中不再可用。因此,编译器将引发异常:

  

名称“ ExpressionHelper”在当前上下文中不存在。

ExpressionHelper功能的正确替代品是什么?

2 个答案:

答案 0 :(得分:8)

可以使用ModelExpressionProvider中的

Microsoft.AspNetCore.Mvc.ViewFeatures

方法GetExpressionText包装与ExpressionHelper相同的方法,并按本Github issue中所述添加其他缓存或结果。

using Microsoft.AspNetCore.Mvc.ViewFeatures;

public static class HtmlHelperExtensions
{
    public static string GetExpressionText<TModel, TResult>(
        this IHtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TResult>> expression)
    {
        var expresionProvider = htmlHelper.ViewContext.HttpContext.RequestServices
            .GetService(typeof(ModelExpressionProvider)) as ModelExpressionProvider;

        return expresionProvider.GetExpressionText(expression);
    }
}

答案 1 :(得分:3)

以下不依赖于IHtmlHelper且可以在其他情况下使用的替代解决方案:

public static class StringExtensions
{
    private static readonly ModelExpressionProvider ModelExpressionProvider = new ModelExpressionProvider(new EmptyModelMetadataProvider());

    public static string GetExpressionText<TEntity, TProperty>(this Expression<Func<TEntity, TProperty>> expression)
    {
        return ModelExpressionProvider.GetExpressionText(expression);
    }
}

要记住的一点是,ModelExpressionProvider拥有内部的ConcurrentDictionary用于缓存,这就是为什么使其静态化可能会有所帮助。

如Nenad所说,ModelExpressionProvider.GetExpressionText只是ExpressionHelper.GetExpressionText的包装,并添加了cache参数:

public class ModelExpressionProvider : IModelExpressionProvider
{
    private readonly IModelMetadataProvider _modelMetadataProvider;
    private readonly ConcurrentDictionary<LambdaExpression, string> _expressionTextCache;
    ....
    public string GetExpressionText<TModel, TValue>(Expression<Func<TModel, TValue>> expression)
    {
        if (expression == null)
        {
            throw new ArgumentNullException(nameof(expression));
        }

        return ExpressionHelper.GetExpressionText(expression, _expressionTextCache);
    }
    ....
}