2010-11-04 10 views

Odpowiedz

6

Obawiam się, że nie ma wbudowanej funkcji sprawdzania, która strona jest fazą cyklu życia strony. Trudno jest dodać tę funkcjonalność bez obsługi wszystkich zdarzeń na samej stronie, ponieważ niektóre zdarzenia są chronione. Dlatego też możesz dziedziczyć klasę LifeCycleListener z Control, dodać ją w konstruktorze do strony nasłuchującej i nadpisać wszystkie zdarzenia.

Jeśli potrzebujesz tylko społeczeństwa „faz” PreInit,Init,Load,DataBinding,PreRender,Unload,Disposed przyjrzeć się następujące podejście (VB.NET, ale myślę, że masz pomysł):

Public Enum LifeCyclePhase 
    AfterPreInit 
    AfterInit 
    AfterLoad 
    AfterDataBinding 
    AfterPreRender 
    AfterUnload 
    AfterDisposed 
End Enum 

Public Interface ITrackingLifeCycle 
    ReadOnly Property GetLifeCycleListener() As LifeCycleListener 
End Interface 

Public Class LifeCycleListener 

    Public Sub New(ByVal ctrl As Control) 
     Me._PageListening = ctrl.Page 
     AddListener() 
    End Sub 

    Private _CurrentPhase As LifeCyclePhase 
    Private _PageListening As Page 

    Public ReadOnly Property CurrentPhase() As LifeCyclePhase 
     Get 
      Return _CurrentPhase 
     End Get 
    End Property 

    Public ReadOnly Property PageListening() As Page 
     Get 
      Return _PageListening 
     End Get 
    End Property 

    Private Sub AddListener() 
     AddHandler _PageListening.PreInit, AddressOf PreInit 
     AddHandler _PageListening.Init, AddressOf Init 
     AddHandler _PageListening.Load, AddressOf Load 
     AddHandler _PageListening.DataBinding, AddressOf DataBinding 
     AddHandler _PageListening.PreRender, AddressOf PreRender 
     AddHandler _PageListening.Unload, AddressOf Unload 
     AddHandler _PageListening.Disposed, AddressOf Disposed 
    End Sub 

    Private Sub PreInit(ByVal sender As Object, ByVal e As EventArgs) 
     Me._CurrentPhase = LifeCyclePhase.AfterPreInit 
    End Sub 

    Private Sub Init(ByVal sender As Object, ByVal e As EventArgs) 
     Me._CurrentPhase = LifeCyclePhase.AfterInit 
    End Sub 

    Private Sub Load(ByVal sender As Object, ByVal e As EventArgs) 
     Me._CurrentPhase = LifeCyclePhase.AfterLoad 
    End Sub 

    Private Sub DataBinding(ByVal sender As Object, ByVal e As EventArgs) 
     Me._CurrentPhase = LifeCyclePhase.AfterDataBinding 
    End Sub 

    Private Sub PreRender(ByVal sender As Object, ByVal e As EventArgs) 
     Me._CurrentPhase = LifeCyclePhase.AfterPreRender 
    End Sub 

    Private Sub Unload(ByVal sender As Object, ByVal e As EventArgs) 
     Me._CurrentPhase = LifeCyclePhase.AfterUnload 
    End Sub 

    Private Sub Disposed(ByVal sender As Object, ByVal e As EventArgs) 
     Me._CurrentPhase = LifeCyclePhase.AfterDisposed 
    End Sub 
End Class 

Handler w tej klasie nazywane są po obsłudze na samej stronie, więc jeśli tak sprawdź CurrentPhase w Page.Init, a otrzymasz PreInit. Dlatego nazwałem tę fazę AfterPreInit.

Partial Public Class _Default 
    Inherits System.Web.UI.Page 
    Implements ITrackingLifeCycle 

    Private lcl As New LifeCycleListener(Me) 

    Public ReadOnly Property GetLifeCycleListener() As LifeCycleListener Implements ITrackingLifeCycle.GetLifeCycleListener 
     Get 
      Return lcl 
     End Get 
    End Property 

Można teraz sprawdzić fazę cyklu życia wszędzie, nawet bez odniesienia do kontroli poprzez HttpContext.Current:

Public Class FooClass 
    Public Shared Sub Foo() 
     If Not (HttpContext.Current Is Nothing OrElse HttpContext.Current.Handler Is Nothing) Then 
      If TypeOf HttpContext.Current.CurrentHandler Is ITrackingLifeCycle Then 
       Dim page As ITrackingLifeCycle = DirectCast(HttpContext.Current.CurrentHandler, ITrackingLifeCycle) 
       Dim phase As LifeCyclePhase = page.GetLifeCycleListener.CurrentPhase 
      End If 
     End If 
    End Sub 
End Class 

To nie jest ani wystarczająco przetestowane ani używany przez siebie i na pewno się do leczenia, ale może to pomaga w twojej obecnej sytuacji.

+0

Fajna wersja kodu - dla mojego szczególnego scenariusza wygląda to na przesadę, ale nadal jestem pod wrażeniem. – cbp

2

O ile mi zrozumieć cykl życia strony, nie można tego zrobić. Zasadniczo klasa strony to facet, który musi podnosić wydarzenia w określonej kolejności. Nie ma nic w budowie, które wskaże etap przetwarzania. Ale aby coś zrobić, możesz utworzyć właściwość i ustawić tę właściwość na różnych etapach przetwarzania.

3

Myślę, że to, co próbujesz osiągnąć, jest pojęciowo niewłaściwe, ponieważ myślisz o wydarzeniach strony jako o stanie strony. Strona nie może być w stanie "OnInit/OnLoad/..." tylko dlatego, że jest wydarzeniem.

Do czego jest potrzebny? może moglibyśmy zaproponować ci lepsze podejście do osiągnięcia twojego celu.

+0

Tworzenie wrappera wokół modułu innej firmy. Moduł wymaga, aby pewne metody były wywoływane podczas OnLoad - nie przed, a nie po. Próbuję "ulepszyć" moduł przez wyrzucenie informacyjnego wyjątku lub przez przekierowanie wywołań podczas OnInit na etap OnLoad - mogę to zrobić, jeśli wiem, na jakim etapie cyklu życia się pracuje. – cbp

+1

Nie zgadzam się z tym, że cykl życia strony nie powinien być traktowany jako stan.Może to być sposób implementowany przez Microsoft, ale udokumentowana koncepcja "cyklu życia strony" jest z pewnością koncepcją opartą na stanie, a w rzeczywistości łatwo jest dziedziczyć po stronie i utworzyć zmienną śledzącą bieżący stan siebie. – cbp

+0

Dlaczego więc nie używasz Delagate? Możesz utworzyć delegata, który wskaże metodę opakowania i wywoła ją w ramach metody OnLoad/OnInit/... –

3

"Poza kontrolą" jest "wewnątrz" innej kontroli lub strony lub czegoś w stanie połączonym z cyklem życia. Znasz jego stan już bez testowania.

+0

Myślę, że widzę, co mówisz, ale nie zawsze tak jest - na pewno nie w moim przypadku. Ale może coś do przemyślenia. – cbp

2

Znalazłem tam jest rzeczywiście nieruchomość wewnętrzna klasy strony, że nie tylko to, czego szukam: jest enum nazywane controlState:

internal enum ControlState 
{ 
Constructed, 
FrameworkInitialized, 
ChildrenInitialized, 
Initialized, 
ViewStateLoaded, 
Loaded, 
PreRendered 
} 

uważam, że jest możliwe, aby uzyskać dostęp do elementów wewnętrznych C# 4, zobacz here

Powiązane problemy