Я пытаюсь использовать контейнер Unity, чтобы упростить юнит-тестирование моих контроллеров. Мой контроллер использует конструктор, который принимает интерфейс к хранилищу. В файле global.asax я создаю экземпляр UnityContainerFactory и регистрирую его в инфраструктуре MVC, а затем регистрирую репозиторий и его реализацию. Я добавил атрибут [Dependency] в параметр репозитория CTOR контроллера. Кажется, что все это работает нормально, за исключением того, что иногда фабричный GetControllerInstance (Type controllerType) вызывается более одного раза и передается пустой аргумент в качестве controllerType.
Первый вызов фабрики всегда корректен, и в качестве аргумента в качестве аргумента передается контроллерный тип «ProductsController». Но иногда фабрика вызывается еще пару раз после отображения представления с нулевым значением для контроллера, и я не уверен, почему. Когда передается правильное значение типа контроллера, «стек вызовов» имеет смысл для меня, но когда передается ноль, я не уверен, почему или кто делает вызов. Есть идеи?
Код и стеки вызовов для примера показаны ниже.
Стек вызовов, когда он работает
Test.DLL! Test.UnityHelpers.UnityControllerFactory.GetControllerInstance (System.Type controllerType = {Name = "ProductsController" FullName = "Test.Controllers.ProductsController"}) Строка 23 C #
Test.DLL! Test._Default.Page_Load (отправитель объекта = {ASP.default_aspx}, System.EventArgs e = {System.EventArgs}) Строка 18 + 0x1a байт C #
стек вызовов при передаче значения NULL в controllerType
Test.DLL! Test.UnityHelpers.UnityControllerFactory.GetControllerInstance (System.Type controllerType = null) Строка 27 C #
Сначала я создал UnityControllerFactory
public class UnityControllerFactory : DefaultControllerFactory
{
UnityContainer container;
public UnityControllerFactory(UnityContainer container)
{
this.container = container;
}
protected override IController GetControllerInstance(Type controllerType)
{
if (controllerType != null)
{
return container.Resolve(controllerType) as IController;
}
else
{
return null; // I never expect to get here, but I do sometimes, the callstack does not show the caller
}
}
}
Затем я добавил следующий код в файл global.asax, чтобы создать экземпляр фабрики контейнеров
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
// Create Unity Container if needed
if (_container == null)
{
_container = new UnityContainer();
}
// Instantiate a new factory
IControllerFactory unityControllerFactory = new UnityControllerFactory(_container);
// Register it with the MVC framework
ControllerBuilder.Current.SetControllerFactory(unityControllerFactory);
// Register the SqlProductRepository
_container.RegisterType<IProductsRepository, SqlProductRepository>
(new ContainerControlledLifetimeManager());
}
Приложение имеет один контроллер
public class ProductsController : Controller
{
public IProductsRepository productsRepository;
public ProductsController([Dependency]IProductsRepository productsRepository)
{
this.productsRepository = productsRepository;
}
}