在扩展方法中使用IoC

时间:2011-07-06 14:50:11

标签: asp.net-mvc ioc-container structuremap

我正在开发一个ASP MVC 3应用程序,我正在编写一个自定义的html助手。它没有什么特别之处或非常复杂,但它需要一个来自结构图的接口实例。我知道我可以简单地从方法内部调用structuremaps的对象工厂,但由于应用程序的其余部分使用IoC而不是服务位置,我希望保持这种方式。

有没有办法从内部和asp net mvc app注入接口到扩展方法?

更新

我正在做的一个例子可能有所帮助:

public static class ShowUrl
{
    public static string ForShow(this UrlHelper url, int showId)
    {
        var service = ObjectFactory.GetInstance<IPerformanceService>();

        var showName = service.GetPerformanceTitle(showId);

        return url.Action(MVC.Performance.Details(showId, showName.ToFriendlyUrl()));
    }
}

使用方法如下:

<a href='<%= Url.ForShow(1)%>'>

基本上我正在尝试使用来自实体ID的slug构建一个URL。也许我只是以一种非常愚蠢的方式来解决这个问题。

3 个答案:

答案 0 :(得分:21)

我不建议这样做。扩展方法通常最好用于直接在类型上的简单,众所周知的操作。如果你的扩展方法依赖于拥有另一种类型的实例,那么很可能它不应该是一个扩展方法。

考虑创建一个执行此功能的实际服务类,并将其注入需要的位置。如果您真的需要在扩展方法中使用它,请考虑将扩展方法所需的功能包装在另一个静态类/方法中,并避免使用任何类型的注入或位置。

分享一些代码可能会更清楚地了解您的具体情况。

答案 1 :(得分:6)

无法将依赖项注入扩展方法。

对于ASP.NET MVC帮助程序,您将不得不做某种服务定位 - 无论您是否通过某种抽象来掩埋它都取决于您。

答案 2 :(得分:6)

您不应该直接在扩展方法中调用structuremap。此外,您应该创建一个可测试版本,该版本采用如下所示的IPerformanceService参数:

public static class ShowUrl
{
    public static string ForShow(this UrlHelper url, int showId)
    {
        //Use the MVC DependencyResolver NOT Structuremap directly (DependencyResolver is using structuremap)
        return url.ForShow(showId, DependencyResolver.Current.GetService<IPerformanceService>())
    }

    //For Unit Testing
    public static string ForShow(this UrlHelper url, int showId, IPerformanceService performanceService)
    {
        var showName = performanceService.GetPerformanceTitle(showId);
        return url.Action(MVC.Performance.Details(showId, showName.ToFriendlyUrl()));
    }
}

现在,您可以在单元测试方法中传递IPerformanceService的具体实现。

Assert.Equal("TheUrl", url.ForShow(8, new PerformanceService());

有关模拟UrlHelper的更多信息:ASP.NET MVC: Unit testing controllers that use UrlHelper