Каков наилучший способ организации решения ASP.Net MVC с использованием инъекции зависимостей?

Я начинаю разработку нового проекта ASP.Net MVC, и я использую этот проект, чтобы попасть в DI. Я уверен, что я собираюсь пойти с Структурной картой, но об этом я не спрашиваю. Я пытаюсь выяснить, как лучше всего организовать мое решение. Сделайте ли проект unit test и модель получить конфигурационный файл для сопоставления их зависимостей или существует ли один класс для их всех?

Кроме того, есть ли какие-либо ловушки для новичков, которых следует избегать, прежде чем я заберусь слишком далеко?

Большое спасибо, всем.....

Обновление Я должен добавить, что когда я говорю "организовать решение", я не имею в виду количество файлов/папок и т.д., А скорее как структурировать классы, связанные с DI. В частности, как управлять загрузчиком. Я вижу, где плохое формулирование с моей стороны может вызвать путаницу.

Ответы

Ответ 1

Чтобы стимулировать улучшение TDD. Имейте два проекта тестирования и/или пространства имен X.Unit.Tests и X.Integrations.Tests.

У меня есть мой код DI в моем основном проекте в "каталоге пространств имен" (/Config), но в моих тестах кода интеграции я могу просто вызвать эти реестры или переопределить, если потребуется в своих базовых устройствах или настройках.

например.

/Config/ServiceRegistry.cs /Config/RepositoryRegistry.cs /Config/Bootstrapper.cs

В global.asax я вызываю Bootstrapper.Init(), и это вызовет x.AddRegistry(новый ServiceRegistry()) и т.д.

В моих модульных тестах вам не нужно использовать DI только в своих интеграционных тестах. В моих тестах IntegrationTests, например. если я тестирую NHibernate через базу данных, я могу инициализировать SM с помощью RepositoryRegistry в TestSetUp с помощью вспомогательного метода, который просто обертывает GetInstance().

Я не отделяюсь от проектов .Bootstraper и .Domain, пока мне не придется... Три проекта, X, X.UnitTests, X.Integration, если вам нужно больше двигаться позже. Я пришел из опыта/компании, чтобы иметь десятки проектов, которые он считал грязными, сначала сокращаясь, но не сейчас, я иду, чтобы быстро ускорить работу и реорганизовать структуру решений, если потребуется.

Ответ 2

Если вы единственный, кто работает над проектом, я бы сделал , что имеет смысл для вас в первую очередь. Ничто не хуже, чем наложение на вас каталога или структуры проекта, которые вы считаете неинтуитивными. Является ли класс BaseController в папке\Core\или\Controller \? Лично я бы посмотрел в Контроллере, но некоторые люди клянутся, что это должно быть в\Core\или\Bases.

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

вторая ловушка для новичков забывает, что по сравнению с другими языками у вас есть преимущество от awesome intellisense, инструментов для навигации по коду и поддержки рефакторинга от Visual Studio. У вас также есть компилятор, который делает работу с файлом намного менее болезненным. Если вы поместите что-то в "неправильное" место, все в порядке, вы всегда можете найти его и перетащить туда, где он должен быть.

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

Лично я склонен помещать интерфейсы с их типами реализации внутри одной и той же папки. IPaymentGateway находится в той же папке, что и AuthorizeNetGateway и PaypalGateway. Если я не могу сразу просмотреть все файлы в этой папке в боковой панели браузера решения, я перемещаю все файлы шлюза в папку \Gateway \.

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

ForRequestedType<Customer>

чище, чем

using KevDog.Models
using Customer=KevDog.Models.Customer

или

ForRequestedType<KevDog.Models.Customer>

Другой способ избежать этой проблемы - быть явным, когда вы именовали вещи: Клиент, CustomerViewModel, CustomerController, CustomerDataRow, CustomerView

Для TDD у вас почти должно быть два загрузчика для управления конкретными типами. Вы действительно не хотите, чтобы ваши модульные тесты использовали AuthorizeNetGateway: IPaymentGateway, скорее StubGateway: IPaymentGateway.

Теперь я также новичок в DI, поэтому я стараюсь сделать вещи очень простыми и зеркально отразить 101 уровень учебников и документации. Включение в динамическую инъекцию на основе конфигурации сборки следует использовать только тогда, когда это требует конкретная ситуация, и вы точно знаете, почему вы это делаете.

Я обычно сохраняю структуру по умолчанию для приложений MVC. Его просто проще иметь код в той же структуре, что и 99% всех учебных пособий и видеороликов.

Надеюсь, что это поможет.

Ответ 3

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

public VatManager()
 : this(new VatManagerRegistry()) { }

public VatManager(Registry registry)
 : this(new Action<IInitializationExpression>(x => { x.AddRegistry(registry); }))
  {
  }

public VatManager(Action<IInitializationExpression> action)
  {
   ObjectFactory.Initialize(action);
   data = ObjectFactory.GetInstance<IVatManagerData>();
  }

У меня три перегрузки конструктора - конструктор по умолчанию без параметров имеет знания о конкретном реестре StructureMap, который необходимо создать для использования в производственном контексте. Другие два позволяют другому коду, который создает этот класс менеджера, чтобы предоставить свой собственный реестр StructureMap или действия, чтобы они могли самостоятельно управлять инъекциями зависимостей, например, в случае автоматизированного теста, предоставляющего mocks вместо конкретных экземпляров этих зависимостей. Я должен добавить, что это решение не относится к контексту ASP.NET MVC и не извлекает никакой информации о конфигурации из файлов *.config.