Ani klasa Page, ani prezenterowie nie powinni zajmować się bezpośrednio zarządzaniem budową lub cyklem życia jakiejkolwiek z jego zależności - to wszystko powinno być obsługiwane przez twój kontener. Ponieważ konstruktor wtrysku nie działa z WebForms, będziesz musiał ujawnić wszelkie potrzebne zależności jako właściwości w klasie. Na przykład, można zmienić klasę:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
public _DefaultPresenter Presenter { get; set; }
}
strona nie powinna potrzebować żadnego odniesienia do repozytorium, jak to będzie wstrzykiwany do prezentera.
Reszta tej odpowiedzi dotyczy StructureMap - szczegóły mogą się różnić w przypadku innych pojemników.
Aby włączyć wstrzyknięcie settera, musisz poinformować StructureMap, które właściwości mają zostać wypełnione. Jednym ze sposobów jest zastosowanie atrybutu [SetterProperty] do samej właściwości. Jednak może to być nieco inwazyjne, aby mieć szczegóły StructureMap w swoich klasach. Innym sposobem jest skonfigurowanie StructureMap, aby wiedziała, które typy właściwości należy wstrzykiwać. Na przykład:
protected void Application_Start(object sender, EventArgs e)
{
ObjectFactory.Initialize(x =>
{
x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
});
x.ForRequestedType<IRepository>().TheDefaultIsConcreteType<Repository>().CacheBy(InstanceScope.Hybrid);
x.SetAllProperties(set => set.WithAnyTypeFromNamespaceContainingType<IRepository>());
});
}
Metoda SetAllProperties pozwala poinformować StructureMap, jak rozpoznać właściwości, które ma wypełnić. W tym przypadku mówię StructureMap, aby wstrzyknąć wszystkich prezenterów (zakładając, że wszyscy są w tej samej przestrzeni nazw).
Nadal należy wykonywać zastrzyk ustawiający przy każdym żądaniu.Za pomocą StructureMap używa się metody BuildUp() w celu wstrzyknięcia zależności do istniejącej instancji. Możesz to zrobić w zdarzeniach Init lub Load każdej strony lub klasy bazowej strony, ale znowu jest to inwazyjne. Aby utrzymać pojemnik z waszych klas stronę, można użyć zdarzenia PreRequestHandlerExecute aplikacji (w global.asax lub IHttpModule):
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
var application = (HttpApplication)sender;
var page = application.Context.CurrentHandler as Page;
if (page == null) return;
ObjectFactory.BuildUp(page);
}
Wreszcie, jeśli chcesz jawnie wyrzucać IRepository, ty mógł poradzić, że w EndRequest imprezy:
protected void Application_EndRequest(object sender, EventArgs e)
{
var disposable = ObjectFactory.GetInstance<IRepository>() as IDisposable;
if (disposable != null) disposable.Dispose();
}
zauważyć, że ta działa poprawnie, ponieważ w inicjalizacji powiedzieliśmy StructureMap do pamięci podręcznej IRepository przez Hybrid, co oznacza „daj mi tę samą instancję dla każdego żądania HTTP (lub wątek, jeśli nie działa w witrynie) ". Po pobraniu elementu IRepository w EndRequest otrzymasz ten sam, który został użyty w żądaniu, i możesz go zutylizować.
Przepraszamy za niedotrzymanie kodu lub tagów w pytaniu! Przerobiłem to teraz - mam nadzieję, że poprawi się sytuacja! Usunie to, jeśli usuniesz swoje ... –