2007-07-27

AutoEventWireup=true

Om du på en Web User Control eller sida skriver AutoEventWireup=True kommer metoder som t.ex. Page_Init() och Page_Load() att automatiskt hakas på sidans Init- resp. Load-event.

Detta är bra ibland, dumt ibland. Smidigt för man slipper haka på eventen själv. Dumt därför att det är något som görs i runtime (tar därmed tid) och kan leda till att event anropas flera gånger.

Exempel: Event-hanterare som anropas två gånger.

protected void Page_Init()
{
Page.Load += Page_Load;
}
protected void Page_Load(object sender, EventArgs e)
{
//This code will execute twice
}

I ovanstående exempel kommer Page_Load att anropas två gånger. En gång eftersom du manuellt hakat på metoden på Load-eventet. Ytterligare en gång därför att AutoEventWireup=true och metoden heter som den gör vilket gör att den automatiskt kommer att hakas på Load-eventet.


AutoEventWireup fungerar  för TemplateControl vilket både Page och Web User Controls ärver av.


Du kan, om du vill dock inte nödvändigt, börja med att läsa K Scott Allens bloggpost om vad AutoEventWireup gör. Det nedan är en fördjupning på ämnet. :)


SupportAutoEvents


Vad händer egentligen när AutoEventWireup=true? En TemplateControl har en property som heter SupportAutoEvents. Denna är true per default (och ändras bara till false av parsern/control buildern som bygger upp kontrollen om man sätter AutoEventWireup=false).


HookUpAutomaticHandlers


TemplateControl.HookUpAutomaticHandlers (vilken anropas under kontrollens OnInit bland annat) kommer om AutoEventWireup=true att försöka hitta följande metoder:



  • Om kontrollen är Page:

    • Page_PreInit
    • Page_PreLoad
    • Page_LoadComplete
    • Page_PreRenderComplete
    • Page_InitComplete
    • Page_SaveStateComplete

  • För alla TemplateControls:

    • Page_Init
    • Page_Load
    • Page_DataBind
    • Page_PreRender
    • Page_Unload
    • Page_Error
    • Page_AbortTransaction eller om den inte finns; OnTransactionAbort
    • Page_CommitTransaction eller om den inte finns; OnTransactionCommit

Detta görs i metoden TemplateControl.GetDelegateInformationWithNoAssert().


32 försök


Som K Scott Allen skriver kommer den för varje metodnamn att försöka två gånger. Först försöker den hitta en EventHandler med det namnet, dvs. en metod med signaturen:

void EventHandler(object sender, EventArgs e)

Exempel: Metod som är en EventHandler

void Page_PreInit(object sender, EventArgs e)

Om det misslyckas kommer den försöka att hitta en VoidMethod, dvs. en metod med signaturen:

void VoidMethod()

Exempel: Metod som är en VoidMethod

void Page_PreInit()

Så om du inte har angivet någon metod alls som matchar något av kriterierna ovan i t.ex. en sida så kommer den ändå att leta efter 32 metoder (och inte 28 som K Scott Allen skrev).


Resultatet av matchningen kommer att lagras i en cache, och kommer därför inte att anropas varje gång. Men det kommer att anropas åtminstone en gång. :)


Haka metoden på eventet


För alla metoder som matchar kriterierna kommer TemplateControl.HookUpAutomaticHandlers() att haka metoden på motsvarande event. Detta kommer dock inte att göras om metoden redan har hakats på eventet eftersom HookUpAutomaticHandlers letar igenom alla event-hanterare för eventet och om den hittar metoden där så struntar den i att lägga till metoden igen.


Men i exemplet ovan så blev ju Page_Load() påhakat två gånger på samma event?
Jepp, men det var för att när vi i Page_Init hakade på eventet så hade HookUpAutomaticHandlers redan gjort det. HookUpAutomaticHandlers anropas ju i OnInit som körs före vår Page_Init. Om vi istället hakar på vårt event före sidans OnInit och därmed före HookUpAutomaticHandlers anropats så kommer Page_Load bara att anropas en gång.


Exempel: Page_Load anropas bara en gång.

public partial class _Default : System.Web.UI.Page
{
public _Default()
{
Page.Load += Page_Load;
}

protected void Page_Load(object sender, EventArgs e)
{
//This code will execute once
}
}

Slutsats: AutoEventWireup=false


Överväg att slå om AutoEventWireup till false (den är true per default) och haka själv på de event du vill använda. Du får mer kontroll över när saker anropas och du slipper den overhead som TemplateControl.HookUpAutomaticHandlers medför.


Microsoft själva rekommenderar att man slår av det när hög prestanda är viktigt.


Mer om AutoEventWireup på MSDN


http://msdn2.microsoft.com/en-us/library/system.web.configuration.pagessection.autoeventwireup.aspx
http://support.microsoft.com/default.aspx/kb/324151

Inga kommentarer: