Próbuję użyć kontenera Unity, aby ułatwić testowanie sterowników. Mój kontroler używa konstruktora, który akceptuje interfejs do repozytorium. W pliku global.asax tworzę egzemplarz UnityContainerFactory i rejestruję go w środowisku MVC, a następnie rejestruję repozytorium i jego implementację. Dodałem atrybut [Dependency] do parametru repozytorium CTOR kontrolera. To wszystko wydaje się działać poprawnie, z tym wyjątkiem, że fabryczny parametr GetControllerInstance (Type controllerType) jest wywoływany więcej niż jeden raz i przekazywany jest zerowy argument jako typ kontrolera.ASP.NET MVC i Unity 1.2 Pytanie dotyczące kontenera
Pierwsze wywołanie do fabryki jest nieprawidłowe, a parametr controllerType "ProductsController" jest przekazywany jako argument. Ale czasami, fabryka jest wywoływana kilka razy po wyświetleniu widoku z zerową wartością dla kontrolera i nie jestem pewien dlaczego. Kiedy zostanie przekazana prawidłowa wartość typu kontrolera, "Stos wywołań" ma sens, ale gdy zostanie przekazana wartość pusta, nie jestem pewien, dlaczego lub kto nawiązuje połączenie. Jakieś pomysły?
Kod i stosy połączeń dla tego przykładu przedstawiono poniżej.
stosu wywołań, gdy działa
Test.DLL! Test.UnityHelpers.UnityControllerFactory.GetControllerInstance (System.Type controllerType = {Name = "ProductsController" FullName = "Test.Controllers.ProductsController"}) Linia 23 C# Test.DLL! Test._Default.Page_Load (object sender = {ASP.default_aspx} System.EventArgs e = {System.EventArgs}) Linia 18 + 0x1a bajtów C#
stosu wywołań kiedy NULL jest przekazywana na controllerType
Test.DLL! Test.UnityHelpers.UnityControllerFactory.GetControllerInstance (Syst em.Type controllerType = null) Linia 27 C#
Najpierw stworzyłem 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
}
}
}
Następnie dodałem poniższy kod pliku Global.asax instancji fabryka pojemnik
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());
}
Aplikacja ma jednego kontrolera:
public class ProductsController : Controller
{
public IProductsRepository productsRepository;
public ProductsController([Dependency]IProductsRepository productsRepository)
{
this.productsRepository = productsRepository;
}
}
Czy jesteś w 100% pewny, że ten wiersz nie zwraca wartości null: return container.Resolve (controllerType) as IController; Wydaje się mało prawdopodobne, ale rzutowanie może łatwo zwrócić wartość null, jeśli wynikowym typem nie był IController lub nie powiodło się wywołanie Resolve. –
Cześć Anderson, Jak widać ze stosu wywołań, przekazywana jest wartość null. Zatrzymałem się również na linii przy użyciu debuggera i jest ona zerowa przed rzutowaniem. To wywołanie jest jedyną funkcją na stosie w danym momencie. Co też nie rozumiem. Test.DLL! Test.UnityHelpers.UnityControllerFactory.GetControllerInstance (System.Type controllerType = null) Linia 27 C# – Rick
Tak myślałem, że widzę w twoim stosie, ale chciałem sprawdzić moje założenia, aby się upewnić. –