【问题标题】:Using IHtmlHelper with Dependency Injection将 IHtmlHelper 与依赖注入一起使用
【发布时间】:2019-03-08 16:34:14
【问题描述】:

我将创建一个控制器,它响应通过 IHtmlHelper 接口创建的第三方 IHtmlContent,而不使用 View() 方法。实际上我正在使用一种解决方法:

我创建了 IHtmlHelper 的扩展函数,其行为类似于“主”,而其他静态函数的行为类似于“从属”。主函数根据它作为参数接收的数据结构调用从属函数。从站基于第三方库创建 IHtmlContent。当所有从机功能完成后,控制器发回响应。 此行为在控制器调用的 cshtml 视图中。

是否可以使用依赖注入将 IHtmlHelper 作为控制器构造函数参数?

类似

public class MyTestController 
{
    private readonly IHtmlHelper _html;

    public MyTestController(IHtmlHelper html) {
     _html = html;
    }
}

如果可能的话,我会简化许多操作,因为我正在使用这个主/从功能来复制一个类的行为

在这里您可以找到一个纯粹的示例,说明我的代码现在如何工作以及我想如何更改它 https://gist.github.com/Blackleones/eb0d02b9dd99164271af88e22143d72b#file-example-cs

我需要这个组件,因为第三方库是 IHtmlHelper 的扩展

【问题讨论】:

  • 我不明白你为什么想要(或需要)控制器中的这个组件。
  • 嗨,DavidG。我在 Gists 上创建了一个示例来解释我为什么想要这个组件。您将看到的代码是一个模拟我想做的纯示例。 gist.github.com/Blackleones/…
  • DavidG 我需要这个组件,因为第三方库是 IHtmlHelper 的扩展

标签: asp.net-core razor


【解决方案1】:

感谢 Itminus 回答我。

但是在控制器构造函数上调用 IHtmlHelper 是不够的,您必须在使用 IHtmlHelper 之前将其上下文化。

我想分享我找到的另一个解决方案并解决我的问题,也许它对其他用户有用。 请参阅https://gist.github.com/Blackleones/eb0d02b9dd99164271af88e22143d72b#file-example-cs 以记住我的目标。

  1. 为了解决我的问题,我创建了一个名为 HtmlHelperAdapter 的类,其中包含一些我需要的实例。
public class MyHtmlHelperAdapter
{
        public IHtmlHelper _html;

        public NubessHtmlHelperAdapter(IHtmlHelper html)
        {
            _html = html;
        }

        public IHtmlHelper Html => _html;
        public ViewContext ViewContext => _html.ViewContext;
        public HttpContext HttpContext => _html.ViewContext.HttpContext;
        public ViewDataDictionary ViewData => _html.ViewData;
        public IServiceProvider provider => _html.ViewContext.HttpContext.RequestServices;
}
  1. 之后我为 IHtmlHelper 创建了一个扩展方法
public static class MyBuilderExtension
{
        public static MyBuilder Nubess(this IHtmlHelper html)
        {
            return new MyBuilder(new MyHtmlHelperAdapter(html));
        }
}

MyBuilder 在哪里

public class MyBuilder
    {
        private readonly MyHtmlHelperAdapter _htmlHelper;

        public MyBuilder(MyHtmlHelperAdapter htmlHelper)
        {
            _htmlHelper = htmlHelper;
        }

        public FormBuilder<object> Form<T>(IDictionary<string, string> customizeArgs = null, FormBuilder<object> externalForm = null)
        {
            return new FormBuilder(_htmlHelper, typeof(T), customizeArgs, externalForm).Build();
        }
    }
  1. 现在我可以使用 class 为视图创建自定义内容,这要归功于 MyHtmlHelperAdapter
 public class FormBuilder
 {
        private MyHtmlHelperAdapter _htmlHelper;
        private readonly IStringLocalizer<SharedResources> _localizer;
        private readonly LinkGenerator _linkGenerator;
        private readonly IEngine _engine;
        private readonly IEngineElement _element;
        private readonly Type _typeDescriptor;
        private readonly IDictionary<string, string> _descriptorArgs;

        /* variabili per semplificare la gestione del builder */
        private readonly FormBuilder<object> Form;
        private readonly FormConfig Config;
        private readonly IList<FormGroupConfig> Groups;
        private readonly IList<FormItemConfig> Items;
        private readonly IDictionary<string, string> FormOptions;

        private readonly string _clientPrefix = "smtForm_{0}_";

        public FormBuilder(MyHtmlHelperAdapter htmlHelper, Type typeDescriptor, IDictionary<string, string> ModelCustomizeArgs = null, FormBuilder<object> externalForm = null)
        {
            _htmlHelper = htmlHelper;
            _localizer = _htmlHelper.provider.GetRequiredService<IStringLocalizer<SharedResources>>() ?? throw new ArgumentNullException();
            _linkGenerator = _htmlHelper.provider.GetRequiredService<LinkGenerator>() ?? throw new ArgumentNullException();
            _engine = _htmlHelper.provider.GetRequiredService<IEngine>() ?? throw new ArgumentNullException();

            //code..
        }


        public FormBuilder<object> Build()
        {
            //code..
            return Form;
        }

     //methods..
}

【讨论】:

    【解决方案2】:

    简答:是的。


    如果你查看the source code of MVC,你会发现IHtmlHelper被注册为一个临时服务:

        internal static void AddViewServices(IServiceCollection services)
        {
    
            ...
    
            //
            // HTML Helper
            //
            services.TryAddTransient<IHtmlHelper, HtmlHelper>();
            services.TryAddTransient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>));
            services.TryAddSingleton<IHtmlGenerator, DefaultHtmlGenerator>();
            services.TryAddSingleton<ModelExpressionProvider>();
            // ModelExpressionProvider caches results. Ensure that it's re-used when the requested type is IModelExpressionProvider.
            services.TryAddSingleton<IModelExpressionProvider>(s => s.GetRequiredService<ModelExpressionProvider>());
            services.TryAddSingleton<ValidationHtmlAttributeProvider, DefaultValidationHtmlAttributeProvider>();
    
            services.TryAddSingleton<IJsonHelper, DefaultJsonHelper>();
    
            ...
    
        }
    

    换句话说,您可以随意注入IHtmlHelper 服务。

    提醒一下,我们应该总是更喜欢在视图层中使用IHtmlHelper

    【讨论】:

      猜你喜欢
      • 2021-02-09
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 1970-01-01
      • 2019-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多