Подтвердить что ты не робот

Использование IoC в методах расширения

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

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

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-адрес с slug из идентификатора объекта. Может быть, я просто буду делать это очень глупо.

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

Ответ 3

Вы не должны вызывать структуру структуры непосредственно в вашем методе расширения. Кроме того, вы должны создать тестовую версию, которая принимает аргумент 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 в свой метод unit test.

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

Дополнительная информация о mocking UrlHelper: ASP.NET MVC: Контроллеры тестирования устройств, использующие UrlHelper