使用 IoC 框架,我需要从注入的类到扩展方法中获取值

本文关键字:扩展 方法 获取 注入 框架 IoC 使用 | 更新日期: 2023-09-27 18:33:20

我有一个相当小的网站,我已经到了需要将我的绝对路径转换为html中的相对路径的地步。 我正在将AutoFac用于我的IoC,并且我构建了一个包装器来在整个项目中注入我的web.config应用程序设置,并且遇到了以下位的墙:

我有一个名为"ContentServerPath"的配置值,我的包装器负责传递它:

public interface IConfigurationWrapper
{
    string ContentServerPath { get; }
}

和我的实现(相当简单(:

public ConfigurationWrapper()
        : this(ConfigurationManager.AppSettings, ConfigurationManager.ConnectionStrings)
    {
    }

    internal ConfigurationWrapper(NameValueCollection appSettings, ConnectionStringSettingsCollection connectionStrings)
    {
        ContentServerPath = appSettings["ContentServerPath"];
    }

我的 _layout.cshtml 页面最初被编码为在开发网站时使用本地样式表和 jquery:

<link rel="stylesheet" type="text/css" href="~/assets/styles/site.css" />

我希望做的最终输出是将 html 行替换为如下内容:

<link rel="stylesheet" type="text/css" href="@Html.GetContentPath("assets/styles/site.css")" />

但是,事实证明这是一项可怕的任务,因为当我调用扩展方法时,我无法将我的 IConfigurationWrapper 注入静态类。

我最初的想法是

public static MvcHtmlString GetContentPath(this HtmlHelper htmlHelper, string relativeContentPath)
    {
        return string.Format("{0}/{1}", _configuration.ContentServerPath, relativeContentPath);
    }

但是,同样,我无法将配置包装器注入静态方法。

作为旁注,我将内容路径放入 web.config 的原因是因为我们有几个不同的测试环境,每个环境都需要自己的内容配置值。 我们依靠构建服务器的 xdt 转换来获取任何更改,然后再部署代码并相应地修改配置。

有人以前遇到过这样的事情并且有一个好的解决方案吗? 提前感谢!

使用 IoC 框架,我需要从注入的类到扩展方法中获取值

考虑允许HtmlHelperExtensions的上下文指定依赖项:

public static class HtmlHelperExtensions
{
    public static MvcHtmlString GetContentPath(this HtmlHelper htmlHelper, string relativeContentPath)
    {
        EnsureWrapper();
        return new MvcHtmlString(string.Format("{0}/{1}", ConfigurationWrapper.ContentServerPath, relativeContentPath));
    }
    public static IConfigurationWrapper ConfigurationWrapper;
    private static void EnsureWrapper()
    {
        if(ConfigurationWrapper == null)
        {
            throw new InvalidOperationException();
        }
    }
}

然后,将其设置在合成根目录中:

HtmlHelperExtensions.ConfigurationWrapper = container.Resolve<IConfigurationWrapper>();

当另一个库要求静态类时,这是一种可靠的模式,相当于静态依赖反转。它强加了最少量的基础设施知识,类似于例如构造函数注入。

你可以更进一步,省去中间人,简化HtmlHelperExtensions并尽可能多地外部化细节:

public static class HtmlHelperExtensions
{
    public static MvcHtmlString GetContentPath(this HtmlHelper htmlHelper, string relativeContentPath)
    {
        EnsureContentServerPath();
        return new MvcHtmlString(string.Format("{0}/{1}", ContentServerPath, relativeContentPath));
    }
    public static string ContentServerPath;
    private static void EnsureContentServerPath()
    {
        if(EnsureContentServerPath == null)
        {
            throw new InvalidOperationException();
        }
    }
}

因此,经过几个小时的研究,我最终在扩展中使用了依赖项解析器来获取我正在寻找的配置值:

public static class HtmlHelperExtensions
{
    public static MvcHtmlString GetContentPath(this HtmlHelper htmlHelper, string relativeContentPath)
    {
        return GetContentPath(relativeContentPath, AutofacDependencyResolver.Current.ApplicationContainer.Resolve<IConfigurationWrapper>());
    }
    internal static MvcHtmlString GetContentPath(string relativeContentPath, IConfigurationWrapper configuration)
    {
        return new MvcHtmlString(string.Format("{0}/{1}", configuration.ContentServerPath, relativeContentPath););
    }
}

希望这至少可以帮助其他人!

-特罗吉