ASP.NET seems to use a cache for this, as @Marc said. See Internal TemplateControl.HookUpAutomaticHandlers .
Part of this method with dotPeek :
internal void HookUpAutomaticHandlers() { ... object obj = TemplateControl._eventListCache[(object) this.GetType()]; if (obj == null) { lock (TemplateControl._lockObject) { obj = TemplateControl._eventListCache[(object) this.GetType()]; if (obj == null) { IDictionary local_1_1 = (IDictionary) new ListDictionary(); this.GetDelegateInformation(local_1_1); obj = local_1_1.Count != 0 ? (object) local_1_1 : TemplateControl._emptyEventSingleton; TemplateControl._eventListCache[(object) this.GetType()] = obj; } } } ...
The private GetDelegateInformation method is responsible for creating delegates for the control. TemplateControl._eventListCache is a Hashtable that contains delegates for each template control.
So, answering your question:
Does he do this for every request?
The answer is no. ASP.NET does this to populate this Hashtable , and then uses cached values.
source share