If you are using .Net 4.5, there is a good way to achieve it. Asp.Net uses ControlBuilder to create temporary cs files from aspx layouts. Prior to .Net 4.5, you can only intercept it by reflecting and switching some internal static variables in the ControlBuilder class.
But in .Net 4.5, they added a new ControlBuilderInterceptor class. Then you can write code like this:
namespace TestInterceptApp { public class BuilderInterceptor : ControlBuilderInterceptor { public override void OnProcessGeneratedCode(ControlBuilder controlBuilder, CodeCompileUnit codeCompileUnit, CodeTypeDeclaration baseType, CodeTypeDeclaration derivedType, CodeMemberMethod buildMethod, CodeMemberMethod dataBindingMethod, IDictionary additionalState) { base.OnProcessGeneratedCode(controlBuilder, codeCompileUnit, baseType, derivedType, buildMethod, dataBindingMethod, additionalState); buildMethod.Statements.Insert( buildMethod.Statements.Count - 1, new CodeSnippetStatement("TestInterceptApp.ControlInterceptor.Intercept(@__ctrl);")); } } }
Then you need to change the compilation section in web.config to register this class in Asp.Net:
<system.web> <compilation debug="true" targetFramework="4.5" controlBuilderInterceptorType="TestInterceptApp.BuilderInterceptor"/> </system.web>
And then you can write this interceptor class as follows:
namespace TestInterceptApp { public static class ControlInterceptor { public static void Intercept(TreeView control) {
Basically, when ControlBuilder creates new cs files, it inserts this line
"TestInterceptApp.ControlInterceptor.Intercept(@__ctrl);"
to the end of each control generation block. You can define one method in the ControlInterceptor class with an object parameter, or you can do a couple of necessary overloads with certain parameters. And plus one basic method with an object parameter. When the CLR executes it, if the TreeView control, then it will send it to fix the method. For all other controls such as Literal, Button, HtmlHead, Page, etc. The CLR will use the method with the signature of the object.
My sample will simply add a new TestNode to each TreeView in the current application that has ID = "tv". And the code generated by ControlBuilder is this:
[System.Diagnostics.DebuggerNonUserCodeAttribute()] private global::System.Web.UI.WebControls.TreeView @__BuildControltv() { global::System.Web.UI.WebControls.TreeView @__ctrl; #line 32 "c:\users\someuser\documents\visual studio 11\Projects\TestInterceptApp\TestInterceptApp\Default.aspx" @__ctrl = new global::System.Web.UI.WebControls.TreeView(); #line default #line hidden this.tv = @__ctrl; @__ctrl.TemplateControl = this; @__ctrl.ApplyStyleSheetSkin(this); #line 32 "c:\users\someuser\documents\visual studio 11\Projects\TestInterceptApp\TestInterceptApp\Default.aspx" @__ctrl.ID = "tv"; #line default #line hidden #line 32 "c:\users\someuser\documents\visual studio 11\Projects\TestInterceptApp\TestInterceptApp\Default.aspx" this.@ __BuildControl__control3(@__ctrl.Nodes); #line default #line hidden