November 2008 - Posts

During a debugging session today Søren and I got to talk about how the Page_Load method on a page is called.

The method is called after the Load event and is declared like this:

   1: protected void Page_Load(object sender, EventArgs e)
   2: {
   3:     
   4: }

 

Taking a look at the Page class in Reflector shows the it inherits from the TemplateControl class. All the following code is extracted using Reflector.

page_load1

If we take a look at the TemplateControl class we can see that following constants are declared:

   1: private const string _onTransactionAbortEventName = "OnTransactionAbort";
   2: private const string _onTransactionCommitEventName = "OnTransactionCommit";
   3: private const string _pageAbortTransactionEventName = "Page_AbortTransaction";
   4: private const string _pageCommitTransactionEventName = "Page_CommitTransaction";
   5: private const string _pageDataBindEventName = "Page_DataBind";
   6: private const string _pageErrorEventName = "Page_Error";
   7: private const string _pageInitCompleteEventName = "Page_InitComplete";
   8: private const string _pageInitEventName = "Page_Init";
   9: private const string _pageLoadCompleteEventName = "Page_LoadComplete";
  10: private const string _pageLoadEventName = "Page_Load";
  11: private const string _pagePreInitEventName = "Page_PreInit";
  12: private const string _pagePreLoadEventName = "Page_PreLoad";
  13: private const string _pagePreRenderCompleteEventName = "Page_PreRenderComplete";
  14: private const string _pagePreRenderEventName = "Page_PreRender";
  15: private const string _pageSaveStateCompleteEventName = "Page_SaveStateComplete";
  16: private const string _pageUnloadEventName = "Page_Unload";

Right there on line 10 you can the name of the Page_Load method declared. If you declare a method with the same signature as the default generated Page_Load method, but name them after the constants declared above they will automatically get called appropriately.

The reason why, is found in the HookUpAutomaticHandlers() method on the TemplateControl class which eventually calls the GetDelegateInformationFromMethod(string, IDictionary) method. The source looks something like this (please excuse the variable naming). Methods are listed in the order which they are called:

   1: internal void HookUpAutomaticHandlers()
   2: {
   3:     if (this.SupportAutoEvents)
   4:     {
   5:         object obj2 = _eventListCache[base.GetType()];
   6:         IDictionary dictionary = null;
   7:         if (obj2 == null)
   8:         {
   9:             lock (_lockObject)
  10:             {
  11:                 obj2 = _eventListCache[base.GetType()];
  12:                 if (obj2 == null)
  13:                 {
  14:                     dictionary = new ListDictionary();
  15:                     this.GetDelegateInformation(dictionary);
  16:                     if (dictionary.Count == 0)
  17:                     {
  18:                         obj2 = _emptyEventSingleton;
  19:                     }
  20:                     else
  21:                     {
  22:                         obj2 = dictionary;
  23:                     }
  24:                     _eventListCache[base.GetType()] = obj2;
  25:                 }
  26:             }
  27:         }
  28:         if (obj2 != _emptyEventSingleton)
  29:         {
  30:             dictionary = (IDictionary) obj2;
  31:             foreach (string str in dictionary.Keys)
  32:             {
  33:                 EventMethodInfo info = (EventMethodInfo) dictionary[str];
  34:                 bool flag = false;
  35:                 MethodInfo methodInfo = info.MethodInfo;
  36:                 Delegate delegate2 = base.Events[_eventObjects[str]];
  37:                 if (delegate2 != null)
  38:                 {
  39:                     foreach (Delegate delegate3 in delegate2.GetInvocationList())
  40:                     {
  41:                         if (delegate3.Method.Equals(methodInfo))
  42:                         {
  43:                             flag = true;
  44:                             break;
  45:                         }
  46:                     }
  47:                 }
  48:                 if (!flag)
  49:                 {
  50:                     IntPtr functionPointer = methodInfo.MethodHandle.GetFunctionPointer();
  51:                     EventHandler handler = new CalliEventHandlerDelegateProxy(this, functionPointer, info.IsArgless).Handler;
  52:                     base.Events.AddHandler(_eventObjects[str], handler);
  53:                 }
  54:             }
  55:         }
  56:     }
  57: }
  58:  
  59: private void GetDelegateInformation(IDictionary dictionary)
  60: {
  61:     if (HttpRuntime.IsFullTrust)
  62:     {
  63:         this.GetDelegateInformationWithNoAssert(dictionary);
  64:     }
  65:     else
  66:     {
  67:         this.GetDelegateInformationWithAssert(dictionary);
  68:     }
  69: }
  70:  
  71: private void GetDelegateInformationWithNoAssert(IDictionary dictionary)
  72: {
  73:     if (this is Page)
  74:     {
  75:         this.GetDelegateInformationFromMethod("Page_PreInit", dictionary);
  76:         this.GetDelegateInformationFromMethod("Page_PreLoad", dictionary);
  77:         this.GetDelegateInformationFromMethod("Page_LoadComplete", dictionary);
  78:         this.GetDelegateInformationFromMethod("Page_PreRenderComplete", dictionary);
  79:         this.GetDelegateInformationFromMethod("Page_InitComplete", dictionary);
  80:         this.GetDelegateInformationFromMethod("Page_SaveStateComplete", dictionary);
  81:     }
  82:     this.GetDelegateInformationFromMethod("Page_Init", dictionary);
  83:     this.GetDelegateInformationFromMethod("Page_Load", dictionary);
  84:     this.GetDelegateInformationFromMethod("Page_DataBind", dictionary);
  85:     this.GetDelegateInformationFromMethod("Page_PreRender", dictionary);
  86:     this.GetDelegateInformationFromMethod("Page_Unload", dictionary);
  87:     this.GetDelegateInformationFromMethod("Page_Error", dictionary);
  88:     if (!this.GetDelegateInformationFromMethod("Page_AbortTransaction", dictionary))
  89:     {
  90:         this.GetDelegateInformationFromMethod("OnTransactionAbort", dictionary);
  91:     }
  92:     if (!this.GetDelegateInformationFromMethod("Page_CommitTransaction", dictionary))
  93:     {
  94:         this.GetDelegateInformationFromMethod("OnTransactionCommit", dictionary);
  95:     }
  96: }
  97:  
  98: private bool GetDelegateInformationFromMethod(string methodName, IDictionary dictionary)
  99: {
 100:     EventHandler handler = (EventHandler) Delegate.CreateDelegate(typeof(EventHandler), this, methodName, true, false);
 101:     if (handler != null)
 102:     {
 103:         dictionary[methodName] = new EventMethodInfo(handler.Method, false);
 104:         return true;
 105:     }
 106:     VoidMethod method = (VoidMethod) Delegate.CreateDelegate(typeof(VoidMethod), this, methodName, true, false);
 107:     if (method != null)
 108:     {
 109:         dictionary[methodName] = new EventMethodInfo(method.Method, true);
 110:         return true;
 111:     }
 112:     return false;
 113: }

On line 15 the delegates are all collected into a dictionary using the GetDelegateInformationFromMethod method. On lines 31 to 53 the MethodInfos are collected, and handlers is added to the events collection. When raising the associated events (e.g. Load for the Page_Load method), the MethodInfo is invoked from the Events-collection.

The HookUpAutomaticHandlers method is called from the SetIntrinsics method on the Page class.

Summary

So to sum up, the Page_Load method and all it's colleagues (Page_Init, Page_DataBind etc.) are not invoked using slow reflection, but is simply grabbed as a named delegate. I'm not used to use these delegates, but from now on I don't see any reason why not to use them, instead of overriding the OnInit, OnPreRender etc. methods.

Well, nothing new in this one, just stuff thats makes me wonder :o)

ms_masthead_ltrAs you might have seen from a previous post I'm pretty excided on Spec# from Microsoft Research, so when my collegue Søren returned from  PDC and he told me that Spec# would replaced by Code Contracts I felt kind of disappointed. However, having looked briefly at Code Contracts I must admit that it looks pretty cool. It is especially worth noticing that Code Contract seems to be working well with Pex. How cool would it be to be able to test your domain model with Pex! Because of this, the next articles on Spec# is put on hold, but will eventually continue as either Code Contracts or Spec# posts (actually hoping it's going to be Code Contracts).

I haven't been able to find more on this anywhere, so please do not just take my word for it. However, a couple of team members are both on the Spec# and the Code Contracts team. Feel free to drop a comment if you have more info on this!

This post has been a couple of days on it's way. The reason for not posting it after each day is that there was not much new that you could not already find on almost every .net blog out there.

Thursday I attended a session on "Velocity", Microsoft's upcoming solution to distributed in-memory cache. This is pretty cool and straight forward (at least for the basic stuff). To demonstrate this, a member of the audience set up Velocity on two servers in a few minutes. This reminded me of the importance of the abstractions we normally use on various features. With a simple abstraction for caching, I really believe you could make the switch to Velocity in a day.

I also attended an XNA session. Before leaving home, I actually decided not to go to that kind of sessions, but as you might have guessed, I changed my mind. Game development is a really hardcore object oriented discipline, and my idea is that a good game developer makes a hardcore application developer, and the session gave a good idea on a completly different way of using objects, methods, loops and more. Pretty cool, if I ever get the time (I doubt it) I'll put my old XBOX 360 to good use with XNA :o)

Friday I attended a very cool session with Udi Dahan on architecture, how to make interfaces concrete, and how he and his team resolved some of their (architectural) issues. Pretty cool guy, and a very inspirering session. I really like the following slide. It's on why to make roles explicit using interfaces.

IMAGE_095

Final Impressions

It has definitely been a unique experience to participate in the conference, I cannot help but to feel kind of privileged to be working in a company that realises this! I have agreed to participate in a podcast by Søren about the general TechEd experience, so stay tuned.

Wow, a lot of cool stuff today!

  • Building custom Linq providers with Bart de Smet (B#) - cool!
  • "Web Scalability and Asynchronous Systems Architecture"
  • Deep reflection with Roy Osherove (from TypeMock), cool guy and a very cool session! Learned a lot about DynamicMethod, Reflection.Emit and IL!
  • Hardcore ASP.NET performance and memory debugging with Tess Ferrandez. This was really cool, something I definitely will be using, so expect some blogposts on this. Until then, take a look at Tess' blog and her BuggyBits lab.
  • Country drinks... 'Nuff said...

Today I attended an introduction to "Oslo", "Dublin" and WF 4.0, Commerce Server "Mojave", ASP.NET MVC basics, ASP.NET MVC tech deep dive, data centric web applications and a very abstract architectural session.

There's really not much to blog about as the web is already full of MVC stuff, which were the most exciting part of the day. Until today I have been somewhat sceptic of ASP.NET MVC as it left me with the same feeling as when I did ASP Classic some years ago.

Today that changed! Jonathan Carter and Hadi Hariri gave some cool presentations showing a lot of nice features. In the last session, Hadi talked about how to customize the various parts of ASP.NET MVC, from controller factories using IoC to implementing custom filters (and a lot more!).

Well, not much to blog about, this post is most to let my colleagues know I'm still alive :-)

Tomorrow is about some more advanced ASP.NET stuff, debugging and performance profiling, and last but definitely not least: Country drinks :-)

So the first "real" day of TechEd is over, and here's some of the things that really impressed me today.

The keynote and "Camano"

Jason Zander gave the keynote, where he showed a lot of the new features of Visual Studio 2010. One thing that was really cool was the "Camano" project. Camano is "just" an application which you connect to your team project in TFS. Testers can then use the software to go through test cases and approve or disapprove a test case. If a test case is disapproved, the tester can submit it as a bug to TFS. This is really cool, because Camano includes screen capture, so the steps to reproduce is recorded as a video in .wmv format. Furthermore, the application's state is captured too, so you can actually debug the application in Visual Studio using the exact state as when the bug occured! In addition, if virtual machines are used for testing, it can recreate the entire state of multiple machines as when the bug appeared. Now we devs have to come up with something else than "it works on my computer" :-)

This is just one feature of Camona, it includes a lot more nice features - can't wait to get my hands on it!

Commerce Server "Mojave"

At the welcome reception after today's sessions, I ran in the Ryan Donovan and Scott Cairney. They gave a live demonstration of the upcomming Commerce Server release, code named "Mojave". Long story short, the next release contains a brand new sleek API, a pure non-COM .NET alternative to pipelines and comes with a very nice SharePoint integration. Furthermore, they demoed the new Silverlight based web tools where they showed live editing of products and variants using the Silverlight based tools - can't wait to try it out! The screenshot below (well, not so much screenshot as "shot-of-a-screen-taken-with-my-mobile") shows the new Starter Site running in SharePoint edit mode.

IMAGE_060

The first CTP is available for download, the next CTP is released in a few weeks, and the final release is scheduled for Q1 2009. Looking forward to it!

Apart from the keynote and the reception I attended an architecture session, as well as a IronPython and IronRuby session - nice stuff too!

Today I arrived at Barcelona to attend TechEd for developers next week. After some waiting, some flight, a little more waiting, a little more flight, and an overly excited Spanish taxi driver I arrived at the hotel, which turned out to be pretty nice!

Upon the registration at the conference center, I got my TechEd swag bag, and here's what it contains:

IMAGE_028

Take a look at the close up of the geeky t-shirt:

IMAGE_029

Thank you Microsoft :-)

More Posts