【问题标题】:How to avoid Service locator / Implement Service locator with CastleWindsor in ASP.NET MVC如何在 ASP.NET MVC 中使用 CastleWindsor 避免服务定位器/实现服务定位器
【发布时间】:2015-12-31 18:20:44
【问题描述】:

我使用 CastleWindsor 作为我的依赖注入框架,当您在 Controller 中时它一切正常,因为我们可以在 controllerfactory 中使用构造函数注入。

但是在某些特定情况下依赖注入(构造函数注入)不起作用。例如:我希望能够在某些实用程序类或扩展方法(例如 HtmlHelper )中使用 IOC 解决我的依赖关系我的意见。我知道有些人不会同意这一点,宁愿保持观点愚蠢,但让我们把它排除在讨论之外。

所以这基本上给我留下了一个选择,那就是使用...服务定位器。所以我知道大多数人认为服务定位器是一种反模式,我明白为什么..但是如果你不能使用依赖注入,你如何解决你与 IOC 的依赖关系?据我所知,使用 IOC 的服务定位器总比什么都没有好。我想避免使用服务定位器模式,但我似乎不明白在某些特定情况下如何避免它。

下一个问题是......所以即使你喜欢/不喜欢服务定位器。哪个是使用 CastleWindsor 实现此功能的最佳选择?

所以我猜选项是:

  1. 将容器公开为全局对象(或通过包装容器的其他全局对象),您可以从代码中的任何位置检索它。然后,您可以在容器上调用 resolve 和 release 方法。我不喜欢的一件事是,我们必须为短暂的生活方式对象显式调用 release。如果没有经验的开发人员不这样做,您最终会出现内存泄漏。

  2. 我还发现:https://www.nuget.org/packages/CommonServiceLocator.WindsorAdapter,它有很多下载..(与选项 1 相同的原理,但更通用并包装容器,因此您可以轻松交换 DI 框架)我查看了代码并我发现适配器只有解析对象的方法。所以我有点想知道为什么没有释放方法。这是否意味着这个包存在临时生活方式对象的内存泄漏问题?

希望有人可以就这些问题给我一些建议!

【问题讨论】:

  • 是否可以将您的实用程序类(我假设它们是静态类或包含静态方法)和扩展方法转换为非静态类并让它们在构造函数中声明它们的依赖关系,以及然后让它们实现一些接口并将它们注入到使用它们的类(我认为是控制器)中?我这么说是因为通常任何需要依赖的东西都不应该是静态方法。

标签: asp.net-mvc dependency-injection castle-windsor castle service-locator


【解决方案1】:

如何避免在静态扩展方法(HTML Helpers)中使用服务定位器?

首先,尽可能避免使用静态扩展方法。当您有小块不太可能更改且没有依赖关系的逻辑(它们适用的类/接口除外)时,静态扩展方法可以很好地工作。当然,这并不总是可行的,但如果您可以使用其他方法,它确实可以大大减少这种情况。

HTML 助手

2017/01/30 更新: 将 DI 与 HTML 帮助程序一起使用的更好方法是使用抽象工厂,如 this answer,它允许对 HTML 帮助程序依赖项进行 DI 容器生命周期管理.

当您确实需要使用静态方法时,注入依赖项的一种方法是使用属性注入。

public static class MyHtmlHelperExtensions
{
    private static IHtmlHelperService htmlHelperService;

    // Property for use with dependency injection in the composition root
    public static IHtmlHelperService HtmlHelperService
    {
        set
        {
            if (value == null)
                throw new ArgumentNullException("value");
            if (htmlHelperService != null)
                throw new ArgumentExeption("HtmlHelperService cannot be set twice");
            htmlHelperService = value;
        }
    }

    // The static method simply calls the instance method of our service,
    // but does not contain any logic.
    public static MvcHtmlString MyHtmlHelper(this HtmlHelper htmlHelper)
    {
        return htmlHelperService.MyHtmlHelper(htmlHelper);
    }
}

基本上,静态 HTML 助手只是一个外观,它将其方法委托给 Aggregate Service,其中包含执行实际工作的真实服务。

HtmlHelperService 是在应用程序启动时在 DI 容器构建后注入的,但仍在应用程序的 composition root 内。

// DIConfig.Register() will create the container and register all of our type mappings.
var container = DIConfig.Register();

// While we are still in the composition root, we instantiate and 
// assign our HtmlHelperService along with its dependency graph.
MyHtmlHelperExtensions.HtmlHelperService = container.Resolve<IHtmlHelperService>();

注意:在 MVC6 中,将有 view components,它更像是控制器而不是静态 HTML 助手,以消除创建具有依赖关系的静态 HTML 助手的需要。

属性

至于Attributes,这是导致服​​务定位器的另一个常见的依赖注入问题来源,最好的方法是define the attribute with no behavior,这可以通过将ActionFilterAttribute派生类型拆分为“哑”属性来完成以及在组合根中解析的 DI 友好的全局操作过滤器。请参阅this MVC IActionFilter examplethis MVC AuthorizeAttribute example

完全没有理由需要一个属性来定义行为,因为属性只定义了可以被另一个服务(它确实有行为)探索的元数据。因此,属性从不需要依赖关系,只有包含行为的服务才需要。

【讨论】:

    猜你喜欢
    • 2014-05-26
    • 2018-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2013-05-20
    • 1970-01-01
    相关资源
    最近更新 更多