Использование IoC в методах расширения - PullRequest
20 голосов
/ 06 июля 2011

Я работаю над приложением ASP MVC 3 и пишу собственный помощник по HTML. В этом нет ничего особенного или чрезвычайно сложного, но для этого потребуется экземпляр интерфейса из карты структуры. Я знаю, что могу просто вызвать объектную фабрику структуры структур изнутри метода, но, поскольку в остальной части приложения используется IoC, а не местоположение службы, я бы хотел оставить его таким.

Есть ли способ внедрить интерфейсы в методы расширения изнутри и приложение asp net mvc?

UPDATE

Пример того, что я делаю, может помочь:

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)%>'>

По сути, я пытаюсь создать URL-адрес с фрагментом из идентификатора объекта. Может быть, я просто делаю это действительно глупо.

Ответы [ 3 ]

21 голосов
/ 06 июля 2011

Я бы не рекомендовал делать это. Методы расширения обычно лучше всего использовать для простых, хорошо известных операций непосредственно над типом. Если ваш метод расширения зависит от наличия экземпляра другого типа, вполне вероятно, что он не должен быть методом расширения с самого начала.

Рассмотрите возможность создания фактического класса обслуживания, который выполняет эту функцию, и внедрения его там, где это необходимо. Если вам действительно нужно это в методе расширения, рассмотрите возможность обернуть функциональность, которая требуется вашему методу расширения, в другой статический класс / метод и избегайте использования каких-либо инъекций или местоположений.

Обмен некоторым кодом может пролить больше света на вашу конкретную ситуацию.

6 голосов
/ 05 сентября 2011

Вы НЕ должны вызывать 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: контроллеры модульного тестирования, использующие UrlHelper

6 голосов
/ 06 июля 2011

Нет способа внедрить зависимости в метод расширения.

Для помощников ASP.NET MVC вам нужно будет найти какое-то расположение службы - будь вы похороните это с какой-то абстракциейзависит от вас.

...