2009-11-10 2 views
0

Я довольно новый для StructureMap, но я понимаю, что есть два способа получения экземпляра из ObjectFactory:Каков наилучший способ внедрения различных реализаций одного и того же интерфейса в контроллер с помощью StructureMap?

  1. По типу (т.е. ObjectFactory.GetInstance<IFoo>())
  2. По типу и названию (т.е. ObjectFactory.GetNamedInstance<IFoo>("foo.bar"))

Я видел множество примеров, демонстрирующих, как создать фабрику контроллеров MVC, которая предоставит экземпляры контроллера с использованием StructureMap, и в большинстве случаев, которые я видел, они используют метод из опции № 1 выше.

Скажем, у нас есть контроллер, который принимает интерфейс хранилища/DAO как конструктор арг ...

public class FooController : Controller 
{ 
    public FooController (IFooRepository fooRepository) 
    { 
    // constructor code goes here 
    } 
} 

Используя класс интерфейса дает мне возможность «впрыснуть» любую реализацию этого интерфейса, чтобы мой контроллер. Что делать, если для двух разных действий я хочу ввести разные реализации? Возможно, в одном случае мне нужна реализация моего репозитория, который будет запрашивать базу данных SQL Server, а в другом случае мне нужна реализация, которая будет получать данные из XML-файла или через вызов веб-службы.

Похоже, что если вы используете метод ObjectFactory.GetInstance(), вы будете ограничены только предоставлением вашему контроллеру единой реализации интерфейса вашего репозитория.

Однако, если вы идете с именованными экземплярами, то вам придется создавать экземпляры на основе имени контроллера, который предоставляет инфраструктура MVC. В большинстве случаев это, как правило, имя контроллера, исходящее из URL-адреса, но это действительно зависит от конфигурации маршрута. Похоже, что это может быть очень запутанным, и будет только более запутанным по мере увеличения количества маршрутов.

Есть ли альтернативный метод, позволяющий использовать разные стратегии создания экземпляров контроллера без использования названных экземпляров? Было бы лучше всего создать отдельные контроллеры и убедиться, что все действия в любом данном контроллере будут действительны для одного и того же конкретного экземпляра класса репозитория/DAO?

ответ

0

Для чего это стоит, я закончил работу с именованными экземплярами, где имена каждого экземпляра основаны на имени контроллера, который структура MVC извлекает из URL-адреса.

Например, URL /foo/DoSomething может получить экземпляр IController из ObjectFactory, созданный с помощью объекта репозитория, который использует API SqlClient для доступа к данным. Затем URL-адрес, такой как /foo.webservice/DoSomething, создаст экземпляр того же конкретного класса контроллера, но передаст конструктору этого экземпляра объект репозитория, который использует веб-службу для доступа к данным.

Существует несколько способов переопределить поведение автоматической компоновки StructureMap для аргументов конструктора. В моем случае я использовал методы CtorDependency и Is и имел сопоставления, которые выглядели примерно так:

// create a named instance for the "foo" controller that uses the SqlClient based repository 
InstanceOf<IController>() 
    .Is.OfConcreteType<FooController>() 
    .CtorDependency<IFooRepository>() 
    .Is(new FooRepositorySql(Constants.FooConnectionString)) 
    .WithName("foo"); 

// create a named instance for the "foo.webservice" controller that uses the Web Service based repository 
InstanceOf<IController>() 
    .Is.OfConcreteType<FooController>() 
    .CtorDependency<IFooRepository>() 
    .Is(new FooRepositoryWs(Constants.FooServiceUrl)) 
    .WithName("foo.webservice"); 
Смежные вопросы