TemplateControl.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Web / UI / TemplateControl.cs / 1305376 / TemplateControl.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 * Page class definition 
 *
 * Copyright (c) 1998 Microsoft Corporation 
 */

namespace System.Web.UI {
 
using System.Text;
using System.Reflection; 
using System; 
using System.IO;
using System.Globalization; 
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using System.Diagnostics; 
using System.ComponentModel;
using System.Resources; 
using System.Web; 
using System.Web.Util;
using System.Web.Compilation; 
using Debug=System.Web.Util.Debug;
using System.Security.Permissions;
using System.Web.Caching;
using System.Xml; 

/* 
 * Base class for Pages and UserControls 
 */
 
/// 
/// Provides the  class and the  class with a base set of functionality.
/// 
public abstract class TemplateControl : Control, INamingContainer, IFilterResolutionService { 

    // Used for the literal string optimization (reading strings from resource) 
    private IntPtr _stringResourcePointer; 
    private int _maxResourceOffset;
    private static object _lockObject = new object(); 

    // Caches the list of auto-hookup methods for each compiled Type (Hashtable).
    // We use a Hashtable instead of the central Cache for optimal performance (VSWhidbey 479476)
    private static Hashtable _eventListCache = new Hashtable(); 

    private static object _emptyEventSingleton = new object(); 
 
    private VirtualPath _virtualPath;
 
    private IResourceProvider _resourceProvider;

    private const string _pagePreInitEventName           = "Page_PreInit";
    private const string _pageInitEventName              = "Page_Init"; 
    private const string _pageInitCompleteEventName      = "Page_InitComplete";
    private const string _pageLoadEventName              = "Page_Load"; 
    private const string _pagePreLoadEventName           = "Page_PreLoad"; 
    private const string _pageLoadCompleteEventName      = "Page_LoadComplete";
    private const string _pagePreRenderCompleteEventName = "Page_PreRenderComplete"; 
    private const string _pageDataBindEventName          = "Page_DataBind";
    private const string _pagePreRenderEventName         = "Page_PreRender";
    private const string _pageSaveStateCompleteEventName = "Page_SaveStateComplete";
    private const string _pageUnloadEventName            = "Page_Unload"; 
    private const string _pageErrorEventName             = "Page_Error";
    private const string _pageAbortTransactionEventName  = "Page_AbortTransaction"; 
    private const string _onTransactionAbortEventName    = "OnTransactionAbort"; 
    private const string _pageCommitTransactionEventName = "Page_CommitTransaction";
    private const string _onTransactionCommitEventName   = "OnTransactionCommit"; 

    private static IDictionary _eventObjects;

    // Used to implement no-compile pages/uc 
    private BuildResultNoCompileTemplateControl _noCompileBuildResult;
 
    static TemplateControl() { 
        _eventObjects = new Hashtable(16);
        _eventObjects.Add(_pagePreInitEventName, Page.EventPreInit); 
        _eventObjects.Add(_pageInitEventName, EventInit);
        _eventObjects.Add(_pageInitCompleteEventName, Page.EventInitComplete);
        _eventObjects.Add(_pageLoadEventName, EventLoad);
        _eventObjects.Add(_pagePreLoadEventName, Page.EventPreLoad); 
        _eventObjects.Add(_pageLoadCompleteEventName, Page.EventLoadComplete);
        _eventObjects.Add(_pagePreRenderCompleteEventName, Page.EventPreRenderComplete); 
        _eventObjects.Add(_pageDataBindEventName, EventDataBinding); 
        _eventObjects.Add(_pagePreRenderEventName, EventPreRender);
        _eventObjects.Add(_pageSaveStateCompleteEventName, Page.EventSaveStateComplete); 
        _eventObjects.Add(_pageUnloadEventName, EventUnload);
        _eventObjects.Add(_pageErrorEventName, EventError);
        _eventObjects.Add(_pageAbortTransactionEventName, EventAbortTransaction);
        _eventObjects.Add(_onTransactionAbortEventName, EventAbortTransaction); 
        _eventObjects.Add(_pageCommitTransactionEventName, EventCommitTransaction);
        _eventObjects.Add(_onTransactionCommitEventName, EventCommitTransaction); 
    } 

 
    protected TemplateControl() {
        Construct();
    }
 

    ///  
    /// Do construction time logic (ASURT 66166) 
    /// 
    protected virtual void Construct() {} 


    private static readonly object EventCommitTransaction = new object();
 

    ///  
    ///    Occurs when a user initiates a transaction. 
    /// 
    [ 
    WebSysDescription(SR.Page_OnCommitTransaction)
    ]
    public event EventHandler CommitTransaction {
        add { 
            Events.AddHandler(EventCommitTransaction, value);
        } 
        remove { 
            Events.RemoveHandler(EventCommitTransaction, value);
        } 
    }

    /// 
    ///    Gets and sets a value indicating whether theme is enabled. 
    /// 
    [ 
    Browsable(true) 
    ]
    public override bool EnableTheming { 
        get {
            return base.EnableTheming;
        }
        set { 
            base.EnableTheming = value;
        } 
    } 

 
    /// 
    /// Raises the  event. You can use this method
    ///    for any transaction processing logic in which your page or user control
    ///    participates. 
    /// 
    protected virtual void OnCommitTransaction(EventArgs e) { 
        EventHandler handler = (EventHandler)Events[EventCommitTransaction]; 
        if (handler != null) handler(this, e);
    } 

    private static readonly object EventAbortTransaction = new object();

 
    /// 
    ///    Occurs when a user aborts a transaction. 
    ///  
    [
    WebSysDescription(SR.Page_OnAbortTransaction) 
    ]
    public event EventHandler AbortTransaction {
        add {
            Events.AddHandler(EventAbortTransaction, value); 
        }
        remove { 
            Events.RemoveHandler(EventAbortTransaction, value); 
        }
    } 


    /// 
    /// Raises the  event. 
    /// 
    protected virtual void OnAbortTransaction(EventArgs e) { 
        EventHandler handler = (EventHandler)Events[EventAbortTransaction]; 
        if (handler != null) handler(this, e);
    } 

    // Page_Error related events/methods

    private static readonly object EventError = new object(); 

 
    ///  
    ///    Occurs when an uncaught exception is thrown.
    ///  
    [
    WebSysDescription(SR.Page_Error)
    ]
    public event EventHandler Error { 
        add {
            Events.AddHandler(EventError, value); 
        } 
        remove {
            Events.RemoveHandler(EventError, value); 
        }
    }

 
    /// 
    /// Raises the  event. 
    ///     
    /// 
    protected virtual void OnError(EventArgs e) { 
        EventHandler handler = (EventHandler)Events[EventError];
        if (handler != null) handler(this, e);
    }
 
    /*
     * Receive a no-compile build result that we call during FrameworkInitialize 
     */ 
    internal void SetNoCompileBuildResult(BuildResultNoCompileTemplateControl noCompileBuildResult) {
        _noCompileBuildResult = noCompileBuildResult; 
    }

    internal bool NoCompile {
        get { return _noCompileBuildResult != null; } 
    }
 
    /* 
     * Method sometime overidden by the generated sub classes.  Users
     * should not override. 
     */

    /// 
    ///  
    ///    Initializes the requested page. While this is sometimes
    ///       overridden when the page is generated at runtime, you should not explicitly override this method. 
    ///  
    [EditorBrowsable(EditorBrowsableState.Never)]
    protected virtual void FrameworkInitialize() { 

        // If it's non-compiled, perform the FrameworkInitialize logic.
        if (NoCompile) {
            if (!HttpRuntime.DisableProcessRequestInApplicationTrust) { 
                // If PermitOnly was disabled in config, we call PermitOnly from here so that at least
                // the control tree creation is protected, as it always is for compiled pages (VSWhidbey 449666) 
                if (HttpRuntime.NamedPermissionSet != null && !HttpRuntime.ProcessRequestInApplicationTrust) { 
                    HttpRuntime.NamedPermissionSet.PermitOnly();
                } 
            }

            _noCompileBuildResult.FrameworkInitialize(this);
        } 
    }
 
    /* 
     * This property is overriden by the generated classes (hence it cannot be internal)
     * If false, we don't do the HookUpAutomaticHandlers() magic. 
     */

    /// 
    ///  
    ///    [To be supplied.]
    ///  
    [EditorBrowsable(EditorBrowsableState.Never)] 
    protected virtual bool SupportAutoEvents  {
        get { return true; } 
    }

    /*
     * Returns a pointer to the resource buffer, and the largest valid offset 
     * in the buffer (for security reason)
     */ 
    internal IntPtr StringResourcePointer { get { return _stringResourcePointer; } } 
    internal int MaxResourceOffset { get { return _maxResourceOffset; } }
 

    // This method is now obsolete.  Ideally, we should get rid of it altogether, but that
    // would be a breaking change (VSWhidbey 464430)
    // We now use the parameter-less override, which is simpler 
    [EditorBrowsable(EditorBrowsableState.Never)]
    public static object ReadStringResource(Type t) { 
        return StringResourceManager.ReadSafeStringResource(t); 
    }
 
    [EditorBrowsable(EditorBrowsableState.Never)]
    public object ReadStringResource() {
        return StringResourceManager.ReadSafeStringResource(GetType());
    } 

 
    ///  
    /// 
    ///    This method is called by the generated classes (hence it cannot be internal) 
    /// 
    protected LiteralControl CreateResourceBasedLiteralControl(int offset, int size, bool fAsciiOnly) {
        return new ResourceBasedLiteralControl(this, offset, size, fAsciiOnly);
    } 

 
    ///  
    /// 
    ///    This method is called by the generated classes (hence it cannot be internal) 
    /// 
    [EditorBrowsable(EditorBrowsableState.Never)]
    protected void SetStringResourcePointer(object stringResourcePointer, int maxResourceOffset) {
 
        // Ignore the passed in maxResourceOffset, which cannot be trusted.  Instead, use
        // the resource size that we obtained from the resource (ASURT 122759) 
        SafeStringResource ssr = (SafeStringResource) stringResourcePointer; 
        _stringResourcePointer = ssr.StringResourcePointer;
        _maxResourceOffset = ssr.ResourceSize; 
    }

    internal VirtualPath VirtualPath {
        get { 
            return _virtualPath;
        } 
    } 

    [ 
    EditorBrowsable(EditorBrowsableState.Advanced),
    Browsable(false)
    ]
    public string AppRelativeVirtualPath { 
        get {
            return VirtualPath.GetAppRelativeVirtualPathString(TemplateControlVirtualPath); 
        } 
        set {
            // Set the TemplateSourceDirectory based on the VirtualPath 
            this.TemplateControlVirtualPath = VirtualPath.CreateNonRelative(value);
        }
    }
 
    internal VirtualPath TemplateControlVirtualPath {
        get { 
            return _virtualPath; 
        }
        set { 
            _virtualPath = value;

            // Set the TemplateSourceDirectory based on the VirtualPath
            this.TemplateControlVirtualDirectory = _virtualPath.Parent; 
        }
    } 
 

    ///  
    ///    Tests if a device filter applies to this request
    /// 
    public virtual bool TestDeviceFilter(string filterName) {
        return(Context.Request.Browser.IsBrowser(filterName)); 
    }
 
 
    /// 
    ///  
    ///    This method is called by the generated classes (hence it cannot be internal)
    /// 
    [EditorBrowsable(EditorBrowsableState.Never)]
    protected void WriteUTF8ResourceString(HtmlTextWriter output, int offset, int size, bool fAsciiOnly) { 

        // Make sure we don't access invalid data 
        checked { 
            if (offset < 0 || size < 0 || offset + size > _maxResourceOffset)
                throw new ArgumentOutOfRangeException("offset"); 
        }

        output.WriteUTF8ResourceString(StringResourcePointer, offset, size, fAsciiOnly);
    } 

    /* 
     * This method is overriden by the generated classes (hence it cannot be internal) 
     */
 
    /// 
    /// 
    /// 
    [EditorBrowsable(EditorBrowsableState.Never)] 
    [Obsolete("Use of this property is not recommended because it is no longer useful. http://go.microsoft.com/fwlink/?linkid=14202")]
    protected virtual int AutoHandlers { 
        get { return 0;} 
        set {}
    } 

    internal override TemplateControl GetTemplateControl() {
        return this;
    } 

    internal void HookUpAutomaticHandlers() { 
        // Do nothing if auto-events are not supported 
        if (!SupportAutoEvents) {
            return; 
        }

        // Get the event list for this Type from our cache, if possible
        object o = _eventListCache[GetType()]; 

        IDictionary dictionary = null; 
 
        // Try to find what handlers are implemented if not tried before
        if (o == null) { 
            lock (_lockObject) {

                // Try the cache again, in case another thread took care of it
                o = _eventListCache[GetType()]; 

                if (o == null) { 
                    dictionary = new ListDictionary(); 

                    GetDelegateInformation(dictionary); 

                    // Cannot find any known handlers.
                    if (dictionary.Count == 0) {
                        o = _emptyEventSingleton; 
                    }
                    else { 
                        o = dictionary; 
                    }
 
                    // Cache it for next time
                    _eventListCache[GetType()] = o;
                }
            } 
        }
 
        // Don't do any thing if no known handlers are found. 
        if (o == _emptyEventSingleton) {
            return; 
        }

        dictionary = (IDictionary)o;
 
        foreach (string key in dictionary.Keys) {
            EventMethodInfo info = (EventMethodInfo)dictionary[key]; 
 
            Debug.Assert(_eventObjects[key] != null);
 
            bool eventExists = false;
            MethodInfo methodInfo = info.MethodInfo;

            Delegate eventDelegates = Events[_eventObjects[key]]; 
            if (eventDelegates != null) {
                foreach (Delegate eventDelegate in eventDelegates.GetInvocationList()) { 
                    // Ignore if this method is already added to the events list. 
                    if (eventDelegate.Method.Equals(methodInfo)) {
                        eventExists = true; 
                        break;
                    }
                }
            } 

            if (!eventExists) { 
                // Create a new Calli delegate proxy 
                IntPtr functionPtr = methodInfo.MethodHandle.GetFunctionPointer();
                EventHandler handler = (new CalliEventHandlerDelegateProxy(this, functionPtr, info.IsArgless)).Handler; 

                // Adds the delegate to events list.
                Events.AddHandler(_eventObjects[key], handler);
            } 
        }
    } 
 
    private void GetDelegateInformation(IDictionary dictionary) {
        if (HttpRuntime.IsFullTrust) { 
            GetDelegateInformationWithNoAssert(dictionary);
        }
        else {
            GetDelegateInformationWithAssert(dictionary); 
        }
    } 
 
    // Make sure we have reflection permission to discover the handlers (ASURT 105965)
    [ReflectionPermission(SecurityAction.Assert, Flags = ReflectionPermissionFlag.MemberAccess)] 
    private void GetDelegateInformationWithAssert(IDictionary dictionary) {
        GetDelegateInformationWithNoAssert(dictionary);
    }
 
    private void GetDelegateInformationWithNoAssert(IDictionary dictionary) {
        if (this is Page) { 
            GetDelegateInformationFromMethod(_pagePreInitEventName, dictionary); 
            GetDelegateInformationFromMethod(_pagePreLoadEventName, dictionary);
            GetDelegateInformationFromMethod(_pageLoadCompleteEventName, dictionary); 
            GetDelegateInformationFromMethod(_pagePreRenderCompleteEventName, dictionary);
            GetDelegateInformationFromMethod(_pageInitCompleteEventName, dictionary);
            GetDelegateInformationFromMethod(_pageSaveStateCompleteEventName, dictionary);
        } 

        GetDelegateInformationFromMethod(_pageInitEventName, dictionary); 
        GetDelegateInformationFromMethod(_pageLoadEventName, dictionary); 
        GetDelegateInformationFromMethod(_pageDataBindEventName, dictionary);
        GetDelegateInformationFromMethod(_pagePreRenderEventName, dictionary); 
        GetDelegateInformationFromMethod(_pageUnloadEventName, dictionary);
        GetDelegateInformationFromMethod(_pageErrorEventName, dictionary);

        if (!GetDelegateInformationFromMethod(_pageAbortTransactionEventName, dictionary)) { 
            GetDelegateInformationFromMethod(_onTransactionAbortEventName, dictionary);
        } 
 
        if (!GetDelegateInformationFromMethod(_pageCommitTransactionEventName, dictionary)) {
            GetDelegateInformationFromMethod(_onTransactionCommitEventName, dictionary); 
        }
    }

    private bool GetDelegateInformationFromMethod(string methodName, IDictionary dictionary) { 

        // First, try to get a delegate to the two parameter handler 
        EventHandler e = (EventHandler)Delegate.CreateDelegate(typeof(EventHandler), this, 
            methodName, true /*ignoreCase*/, false /*throwOnBindFailure*/);
 
        if (e != null) {
            dictionary[methodName] = new EventMethodInfo(e.Method, false);
            return true;
        } 

        // If there isn't one, try the argless one 
        VoidMethod vm = (VoidMethod)Delegate.CreateDelegate(typeof(VoidMethod), this, 
            methodName, true /*ignoreCase*/, false /*throwOnBindFailure*/);
        if (vm != null) { 
            dictionary[methodName] = new EventMethodInfo(vm.Method, true);
            return true;
        }
 
        return false;
    } 
 

    ///  
    /// Obtains a  object from a user control file.
    /// 
    public Control LoadControl(string virtualPath) {
 
        return LoadControl(VirtualPath.Create(virtualPath));
    } 
 
    internal Control LoadControl(VirtualPath virtualPath) {
 
        // If it's relative, make it *app* relative.  Treat is as relative to this
        // user control (ASURT 55513)
        virtualPath = VirtualPath.Combine(this.TemplateControlVirtualDirectory, virtualPath);
 
        // Process the user control and get its BuildResult
        BuildResult result = BuildManager.GetVPathBuildResult(Context, virtualPath); 
 
        return LoadControl((IWebObjectFactory)result, virtualPath, null /*Type*/, null /*parameters*/);
    } 

    // Make sure we have reflection permission to use GetMethod below (ASURT 106196)
    [ReflectionPermission(SecurityAction.Assert, Flags=ReflectionPermissionFlag.MemberAccess)]
    private void AddStackContextToHashCode(HashCodeCombiner combinedHashCode) { 

        StackTrace st = new StackTrace(); 
 
        // First, skip all the stack frames that are in the TemplateControl class, as
        // they are irrelevant to the hash.  Start the search at 2 since we know for sure 
        // that this method and its caller are in TemplateControl.
        int startingUserFrame = 2;
        for (; ; startingUserFrame++) {
            StackFrame f = st.GetFrame(startingUserFrame); 
            if (f.GetMethod().DeclaringType != typeof(TemplateControl)) {
                break; 
            } 
        }
 
        // Get a cache key based on the top two items of the caller's stack.
        // It's not guaranteed unique, but for all common cases, it will be
        for (int i = startingUserFrame; i < startingUserFrame + 2; i++) {
            StackFrame f = st.GetFrame(i); 

            MethodBase m = f.GetMethod(); 
            combinedHashCode.AddObject(m.DeclaringType.AssemblyQualifiedName); 
            combinedHashCode.AddObject(m.Name);
            combinedHashCode.AddObject(f.GetNativeOffset()); 
        }
    }

 
    public Control LoadControl(Type t, object[] parameters) {
 
        return LoadControl(null /*IWebObjectFactory*/, null /*virtualPath*/, t, parameters); 
    }
 

    private Control LoadControl(IWebObjectFactory objectFactory, VirtualPath virtualPath, Type t, object[] parameters) {

        // Make sure we get an object factory or a type, but not both 
        Debug.Assert((objectFactory == null) != (t == null));
 
        BuildResultCompiledType compiledUCResult = null; 
        BuildResultNoCompileUserControl noCompileUCResult = null;
 
        if (objectFactory != null) {
            // It can be a compiled or no-compile user control
            compiledUCResult = objectFactory as BuildResultCompiledType;
            if (compiledUCResult != null) { 
                t = compiledUCResult.ResultType;
                Debug.Assert(t != null); 
 
                // Make sure it's a user control (VSWhidbey 428718)
                Util.CheckAssignableType(typeof(UserControl), t); 
            }
            else {
                noCompileUCResult = (BuildResultNoCompileUserControl)objectFactory;
                Debug.Assert(noCompileUCResult != null); 
            }
        } 
        else { 
            // Make sure the type has the correct base class (ASURT 123677)
            if (t != null) 
                Util.CheckAssignableType(typeof(Control), t);
        }

        PartialCachingAttribute cacheAttrib; 

        // Check if the user control has a PartialCachingAttribute attribute 
        if (t != null) { 
            cacheAttrib = (PartialCachingAttribute)
                TypeDescriptor.GetAttributes(t)[typeof(PartialCachingAttribute)]; 
        }
        else {
            cacheAttrib = noCompileUCResult.CachingAttribute;
        } 

        if (cacheAttrib == null) { 
            // The control is not cached.  Just create it. 
            Control c;
            if (objectFactory != null) { 
                c = (Control) objectFactory.CreateInstance();
            }
            else {
                c = (Control) HttpRuntime.CreatePublicInstance(t, parameters); 
            }
 
            // If it's a user control, do some extra initialization 
            UserControl uc = c as UserControl;
            if (uc != null) { 
                Debug.Assert(virtualPath != null);
                if (virtualPath != null)
                    uc.TemplateControlVirtualPath = virtualPath;
                uc.InitializeAsUserControl(Page); 
            }
 
            return c; 
        }
 
        HashCodeCombiner combinedHashCode = new HashCodeCombiner();

        // Start by adding the type or object factory of the user control to the hash.
        // This guarantees that two unrelated user controls don't share the same cached data. 
        if (objectFactory != null) {
            combinedHashCode.AddObject(objectFactory); 
        } 
        else {
            combinedHashCode.AddObject(t); 
        }

        // If it's not shared, add some stack frames to the hash
        if (!cacheAttrib.Shared) { 
            AddStackContextToHashCode(combinedHashCode);
        } 
 
        string cacheKey = combinedHashCode.CombinedHashString;
 
        // Wrap it to allow it to be cached
        return new PartialCachingControl(objectFactory, t, cacheAttrib, "_" + cacheKey, parameters);
    }
 
    // Class that implements the templates returned by LoadTemplate (ASURT 94138)
    internal class SimpleTemplate : ITemplate { 
        private IWebObjectFactory _objectFactory; 

        internal SimpleTemplate(ITypedWebObjectFactory objectFactory) { 

            // Make sure it's a user control (VSWhidbey 428718)
            Util.CheckAssignableType(typeof(UserControl), objectFactory.InstantiatedType);
 
            _objectFactory = objectFactory;
        } 
 
        public virtual void InstantiateIn(Control control) {
            UserControl uc = (UserControl)_objectFactory.CreateInstance(); 

            uc.InitializeAsUserControl(control.Page);

            control.Controls.Add(uc); 
        }
    } 
 

    ///  
    ///    
    ///       Obtains an instance of the  interface from an
    ///       external file.
    ///     
    /// 
    public ITemplate LoadTemplate(string virtualPath) { 
        return LoadTemplate(VirtualPath.Create(virtualPath)); 
    }
 
    internal ITemplate LoadTemplate(VirtualPath virtualPath) {

        // If it's relative, make it *app* relative.  Treat is as relative to this
        // user control (ASURT 55513) 
        virtualPath = VirtualPath.Combine(TemplateControlVirtualDirectory, virtualPath);
 
        // Compile the declarative template and get its object factory 
        ITypedWebObjectFactory objectFactory = (ITypedWebObjectFactory)BuildManager.GetVPathBuildResult(
            Context, virtualPath); 

        return new SimpleTemplate(objectFactory);
    }
 

    ///  
    ///     Parse the input string into a Control.  Looks for the first control 
    ///    in the input.  Returns null if none is found.
    ///  
    public Control ParseControl(string content) {
        return ParseControl(content, true);
    }
 
    public Control ParseControl(string content, bool ignoreParserFilter) {
        return TemplateParser.ParseControl(content, VirtualPath.Create(AppRelativeVirtualPath), ignoreParserFilter); 
    } 

#if NOTYET 

    /// 
    ///     Parse the input string into an ITemplate.
    ///  
    internal ITemplate ParseTemplate(string content) {
        return TemplateParser.ParseTemplate(content, AppRelativeTemplateSourceDirectory); 
    } 
#endif
 
    /// 
    /// Used by simplified databinding methods to ensure they can only be called when the control is on a page.
    /// 
    private void CheckPageExists() { 
        if (Page == null) {
            throw new InvalidOperationException(SR.GetString(SR.TemplateControl_DataBindingRequiresPage)); 
        } 
    }
 

    /// 
    /// Simplified databinding Eval() method. This method uses the current data item to evaluate an expression using DataBinder.Eval().
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'. 
    /// If the data item is not found, an exception is thrown.
    ///  
    protected internal object Eval(string expression) { 
        CheckPageExists();
        return DataBinder.Eval(Page.GetDataItem(), expression); 
    }


    ///  
    /// Simplified databinding Eval() method with a format expression. This method uses the current data item to evaluate an expression using DataBinder.Eval().
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'. 
    /// If the data item is not found, an exception is thrown. 
    /// 
    protected internal string Eval(string expression, string format) { 
        CheckPageExists();
        return DataBinder.Eval(Page.GetDataItem(), expression, format);
    }
 

    ///  
    /// Simplified databinding XPath() method. This method uses the current data item to evaluate an XPath expression using XPathBinder.Eval(). 
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'.
    /// If the data item is not found, an exception is thrown. 
    /// 
    protected internal object XPath(string xPathExpression) {
        CheckPageExists();
        return XPathBinder.Eval(Page.GetDataItem(), xPathExpression); 
    }
 
    ///  
    /// Simplified databinding XPath() method. This method uses the current data item and a namespace resolver
    /// to evaluate an XPath expression using XPathBinder.Eval(). 
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'.
    /// If the data item is not found, an exception is thrown.
    /// 
    protected internal object XPath(string xPathExpression, IXmlNamespaceResolver resolver) { 
        CheckPageExists();
        return XPathBinder.Eval(Page.GetDataItem(), xPathExpression, resolver); 
    } 

 
    /// 
    /// Simplified databinding XPath() method with a format expression. This method uses the current data item to evaluate an XPath expression using XPathBinder.Eval().
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'.
    /// If the data item is not found, an exception is thrown. 
    /// 
    protected internal string XPath(string xPathExpression, string format) { 
        CheckPageExists(); 
        return XPathBinder.Eval(Page.GetDataItem(), xPathExpression, format);
    } 

    /// 
    /// Simplified databinding XPath() method with a format expression. This method uses the current data item and a namespace resolver
    /// to evaluate an XPath expression using XPathBinder.Eval(). 
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'.
    /// If the data item is not found, an exception is thrown. 
    ///  
    protected internal string XPath(string xPathExpression, string format, IXmlNamespaceResolver resolver) {
        CheckPageExists(); 
        return XPathBinder.Eval(Page.GetDataItem(), xPathExpression, format, resolver);
    }

 
    /// 
    /// Simplified databinding XPathSelect() method. This method uses the current data item to evaluate an XPath expression that returns a node list using XPathBinder.Select(). 
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'. 
    /// If the data item is not found, an exception is thrown.
    ///  
    protected internal IEnumerable XPathSelect(string xPathExpression) {
        CheckPageExists();
        return XPathBinder.Select(Page.GetDataItem(), xPathExpression);
    } 

    ///  
    /// Simplified databinding XPathSelect() method. This method uses the current data item and a namespace resolver 
    /// to evaluate an XPath expression that returns a node list using XPathBinder.Select().
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'. 
    /// If the data item is not found, an exception is thrown.
    /// 
    protected internal IEnumerable XPathSelect(string xPathExpression, IXmlNamespaceResolver resolver) {
        CheckPageExists(); 
        return XPathBinder.Select(Page.GetDataItem(), xPathExpression, resolver);
    } 
 

    ///  
    /// Return a Page-level resource object
    /// 
    protected object GetLocalResourceObject(string resourceKey) {
 
        // Cache the resource provider in the template control, so that if a Page needs to call
        // this multiple times, we don't need to call ResourceExpressionBuilder.GetLocalResourceProvider 
        // every time. 
        if (_resourceProvider == null)
            _resourceProvider = ResourceExpressionBuilder.GetLocalResourceProvider(this); 

        return ResourceExpressionBuilder.GetResourceObject(_resourceProvider, resourceKey, null /*culture*/);
    }
 
    protected object GetLocalResourceObject(string resourceKey, Type objType, string propName) {
 
        // Cache the resource provider in the template control, so that if a Page needs to call 
        // this multiple times, we don't need to call ResourceExpressionBuilder.GetLocalResourceProvider
        // every time. 
        if (_resourceProvider == null)
            _resourceProvider = ResourceExpressionBuilder.GetLocalResourceProvider(this);

        return ResourceExpressionBuilder.GetResourceObject(_resourceProvider, 
            resourceKey, null /*culture*/, objType, propName);
    } 
 

    ///  
    /// Return an App-level resource object
    /// 
    protected object GetGlobalResourceObject(string className, string resourceKey) {
        return ResourceExpressionBuilder.GetGlobalResourceObject(className, resourceKey, null, null, null); 
    }
 
    protected object GetGlobalResourceObject(string className, string resourceKey, Type objType, string propName) { 
        return ResourceExpressionBuilder.GetGlobalResourceObject(className, resourceKey, objType, propName, null);
    } 

    #region IFilterResolutionService

    ///  
    bool IFilterResolutionService.EvaluateFilter(string filterName) {
        return TestDeviceFilter(filterName); 
    } 

 
    /// 
    int IFilterResolutionService.CompareFilters(string filter1, string filter2) {
        return BrowserCapabilitiesCompiler.BrowserCapabilitiesFactory.CompareFilters(filter1, filter2);
    } 
    #endregion
 
    // Internal helper class for storing the event info 
    private class EventMethodInfo {
        private bool _isArgless; 
        private MethodInfo _methodInfo;

        internal EventMethodInfo(MethodInfo methodInfo, bool isArgless) {
            _isArgless = isArgless; 
            _methodInfo = methodInfo;
        } 
 
        internal bool IsArgless { get { return _isArgless; } }
        internal MethodInfo MethodInfo { get { return _methodInfo; } } 
    }
}
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 * Page class definition 
 *
 * Copyright (c) 1998 Microsoft Corporation 
 */

namespace System.Web.UI {
 
using System.Text;
using System.Reflection; 
using System; 
using System.IO;
using System.Globalization; 
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using System.Diagnostics; 
using System.ComponentModel;
using System.Resources; 
using System.Web; 
using System.Web.Util;
using System.Web.Compilation; 
using Debug=System.Web.Util.Debug;
using System.Security.Permissions;
using System.Web.Caching;
using System.Xml; 

/* 
 * Base class for Pages and UserControls 
 */
 
/// 
/// Provides the  class and the  class with a base set of functionality.
/// 
public abstract class TemplateControl : Control, INamingContainer, IFilterResolutionService { 

    // Used for the literal string optimization (reading strings from resource) 
    private IntPtr _stringResourcePointer; 
    private int _maxResourceOffset;
    private static object _lockObject = new object(); 

    // Caches the list of auto-hookup methods for each compiled Type (Hashtable).
    // We use a Hashtable instead of the central Cache for optimal performance (VSWhidbey 479476)
    private static Hashtable _eventListCache = new Hashtable(); 

    private static object _emptyEventSingleton = new object(); 
 
    private VirtualPath _virtualPath;
 
    private IResourceProvider _resourceProvider;

    private const string _pagePreInitEventName           = "Page_PreInit";
    private const string _pageInitEventName              = "Page_Init"; 
    private const string _pageInitCompleteEventName      = "Page_InitComplete";
    private const string _pageLoadEventName              = "Page_Load"; 
    private const string _pagePreLoadEventName           = "Page_PreLoad"; 
    private const string _pageLoadCompleteEventName      = "Page_LoadComplete";
    private const string _pagePreRenderCompleteEventName = "Page_PreRenderComplete"; 
    private const string _pageDataBindEventName          = "Page_DataBind";
    private const string _pagePreRenderEventName         = "Page_PreRender";
    private const string _pageSaveStateCompleteEventName = "Page_SaveStateComplete";
    private const string _pageUnloadEventName            = "Page_Unload"; 
    private const string _pageErrorEventName             = "Page_Error";
    private const string _pageAbortTransactionEventName  = "Page_AbortTransaction"; 
    private const string _onTransactionAbortEventName    = "OnTransactionAbort"; 
    private const string _pageCommitTransactionEventName = "Page_CommitTransaction";
    private const string _onTransactionCommitEventName   = "OnTransactionCommit"; 

    private static IDictionary _eventObjects;

    // Used to implement no-compile pages/uc 
    private BuildResultNoCompileTemplateControl _noCompileBuildResult;
 
    static TemplateControl() { 
        _eventObjects = new Hashtable(16);
        _eventObjects.Add(_pagePreInitEventName, Page.EventPreInit); 
        _eventObjects.Add(_pageInitEventName, EventInit);
        _eventObjects.Add(_pageInitCompleteEventName, Page.EventInitComplete);
        _eventObjects.Add(_pageLoadEventName, EventLoad);
        _eventObjects.Add(_pagePreLoadEventName, Page.EventPreLoad); 
        _eventObjects.Add(_pageLoadCompleteEventName, Page.EventLoadComplete);
        _eventObjects.Add(_pagePreRenderCompleteEventName, Page.EventPreRenderComplete); 
        _eventObjects.Add(_pageDataBindEventName, EventDataBinding); 
        _eventObjects.Add(_pagePreRenderEventName, EventPreRender);
        _eventObjects.Add(_pageSaveStateCompleteEventName, Page.EventSaveStateComplete); 
        _eventObjects.Add(_pageUnloadEventName, EventUnload);
        _eventObjects.Add(_pageErrorEventName, EventError);
        _eventObjects.Add(_pageAbortTransactionEventName, EventAbortTransaction);
        _eventObjects.Add(_onTransactionAbortEventName, EventAbortTransaction); 
        _eventObjects.Add(_pageCommitTransactionEventName, EventCommitTransaction);
        _eventObjects.Add(_onTransactionCommitEventName, EventCommitTransaction); 
    } 

 
    protected TemplateControl() {
        Construct();
    }
 

    ///  
    /// Do construction time logic (ASURT 66166) 
    /// 
    protected virtual void Construct() {} 


    private static readonly object EventCommitTransaction = new object();
 

    ///  
    ///    Occurs when a user initiates a transaction. 
    /// 
    [ 
    WebSysDescription(SR.Page_OnCommitTransaction)
    ]
    public event EventHandler CommitTransaction {
        add { 
            Events.AddHandler(EventCommitTransaction, value);
        } 
        remove { 
            Events.RemoveHandler(EventCommitTransaction, value);
        } 
    }

    /// 
    ///    Gets and sets a value indicating whether theme is enabled. 
    /// 
    [ 
    Browsable(true) 
    ]
    public override bool EnableTheming { 
        get {
            return base.EnableTheming;
        }
        set { 
            base.EnableTheming = value;
        } 
    } 

 
    /// 
    /// Raises the  event. You can use this method
    ///    for any transaction processing logic in which your page or user control
    ///    participates. 
    /// 
    protected virtual void OnCommitTransaction(EventArgs e) { 
        EventHandler handler = (EventHandler)Events[EventCommitTransaction]; 
        if (handler != null) handler(this, e);
    } 

    private static readonly object EventAbortTransaction = new object();

 
    /// 
    ///    Occurs when a user aborts a transaction. 
    ///  
    [
    WebSysDescription(SR.Page_OnAbortTransaction) 
    ]
    public event EventHandler AbortTransaction {
        add {
            Events.AddHandler(EventAbortTransaction, value); 
        }
        remove { 
            Events.RemoveHandler(EventAbortTransaction, value); 
        }
    } 


    /// 
    /// Raises the  event. 
    /// 
    protected virtual void OnAbortTransaction(EventArgs e) { 
        EventHandler handler = (EventHandler)Events[EventAbortTransaction]; 
        if (handler != null) handler(this, e);
    } 

    // Page_Error related events/methods

    private static readonly object EventError = new object(); 

 
    ///  
    ///    Occurs when an uncaught exception is thrown.
    ///  
    [
    WebSysDescription(SR.Page_Error)
    ]
    public event EventHandler Error { 
        add {
            Events.AddHandler(EventError, value); 
        } 
        remove {
            Events.RemoveHandler(EventError, value); 
        }
    }

 
    /// 
    /// Raises the  event. 
    ///     
    /// 
    protected virtual void OnError(EventArgs e) { 
        EventHandler handler = (EventHandler)Events[EventError];
        if (handler != null) handler(this, e);
    }
 
    /*
     * Receive a no-compile build result that we call during FrameworkInitialize 
     */ 
    internal void SetNoCompileBuildResult(BuildResultNoCompileTemplateControl noCompileBuildResult) {
        _noCompileBuildResult = noCompileBuildResult; 
    }

    internal bool NoCompile {
        get { return _noCompileBuildResult != null; } 
    }
 
    /* 
     * Method sometime overidden by the generated sub classes.  Users
     * should not override. 
     */

    /// 
    ///  
    ///    Initializes the requested page. While this is sometimes
    ///       overridden when the page is generated at runtime, you should not explicitly override this method. 
    ///  
    [EditorBrowsable(EditorBrowsableState.Never)]
    protected virtual void FrameworkInitialize() { 

        // If it's non-compiled, perform the FrameworkInitialize logic.
        if (NoCompile) {
            if (!HttpRuntime.DisableProcessRequestInApplicationTrust) { 
                // If PermitOnly was disabled in config, we call PermitOnly from here so that at least
                // the control tree creation is protected, as it always is for compiled pages (VSWhidbey 449666) 
                if (HttpRuntime.NamedPermissionSet != null && !HttpRuntime.ProcessRequestInApplicationTrust) { 
                    HttpRuntime.NamedPermissionSet.PermitOnly();
                } 
            }

            _noCompileBuildResult.FrameworkInitialize(this);
        } 
    }
 
    /* 
     * This property is overriden by the generated classes (hence it cannot be internal)
     * If false, we don't do the HookUpAutomaticHandlers() magic. 
     */

    /// 
    ///  
    ///    [To be supplied.]
    ///  
    [EditorBrowsable(EditorBrowsableState.Never)] 
    protected virtual bool SupportAutoEvents  {
        get { return true; } 
    }

    /*
     * Returns a pointer to the resource buffer, and the largest valid offset 
     * in the buffer (for security reason)
     */ 
    internal IntPtr StringResourcePointer { get { return _stringResourcePointer; } } 
    internal int MaxResourceOffset { get { return _maxResourceOffset; } }
 

    // This method is now obsolete.  Ideally, we should get rid of it altogether, but that
    // would be a breaking change (VSWhidbey 464430)
    // We now use the parameter-less override, which is simpler 
    [EditorBrowsable(EditorBrowsableState.Never)]
    public static object ReadStringResource(Type t) { 
        return StringResourceManager.ReadSafeStringResource(t); 
    }
 
    [EditorBrowsable(EditorBrowsableState.Never)]
    public object ReadStringResource() {
        return StringResourceManager.ReadSafeStringResource(GetType());
    } 

 
    ///  
    /// 
    ///    This method is called by the generated classes (hence it cannot be internal) 
    /// 
    protected LiteralControl CreateResourceBasedLiteralControl(int offset, int size, bool fAsciiOnly) {
        return new ResourceBasedLiteralControl(this, offset, size, fAsciiOnly);
    } 

 
    ///  
    /// 
    ///    This method is called by the generated classes (hence it cannot be internal) 
    /// 
    [EditorBrowsable(EditorBrowsableState.Never)]
    protected void SetStringResourcePointer(object stringResourcePointer, int maxResourceOffset) {
 
        // Ignore the passed in maxResourceOffset, which cannot be trusted.  Instead, use
        // the resource size that we obtained from the resource (ASURT 122759) 
        SafeStringResource ssr = (SafeStringResource) stringResourcePointer; 
        _stringResourcePointer = ssr.StringResourcePointer;
        _maxResourceOffset = ssr.ResourceSize; 
    }

    internal VirtualPath VirtualPath {
        get { 
            return _virtualPath;
        } 
    } 

    [ 
    EditorBrowsable(EditorBrowsableState.Advanced),
    Browsable(false)
    ]
    public string AppRelativeVirtualPath { 
        get {
            return VirtualPath.GetAppRelativeVirtualPathString(TemplateControlVirtualPath); 
        } 
        set {
            // Set the TemplateSourceDirectory based on the VirtualPath 
            this.TemplateControlVirtualPath = VirtualPath.CreateNonRelative(value);
        }
    }
 
    internal VirtualPath TemplateControlVirtualPath {
        get { 
            return _virtualPath; 
        }
        set { 
            _virtualPath = value;

            // Set the TemplateSourceDirectory based on the VirtualPath
            this.TemplateControlVirtualDirectory = _virtualPath.Parent; 
        }
    } 
 

    ///  
    ///    Tests if a device filter applies to this request
    /// 
    public virtual bool TestDeviceFilter(string filterName) {
        return(Context.Request.Browser.IsBrowser(filterName)); 
    }
 
 
    /// 
    ///  
    ///    This method is called by the generated classes (hence it cannot be internal)
    /// 
    [EditorBrowsable(EditorBrowsableState.Never)]
    protected void WriteUTF8ResourceString(HtmlTextWriter output, int offset, int size, bool fAsciiOnly) { 

        // Make sure we don't access invalid data 
        checked { 
            if (offset < 0 || size < 0 || offset + size > _maxResourceOffset)
                throw new ArgumentOutOfRangeException("offset"); 
        }

        output.WriteUTF8ResourceString(StringResourcePointer, offset, size, fAsciiOnly);
    } 

    /* 
     * This method is overriden by the generated classes (hence it cannot be internal) 
     */
 
    /// 
    /// 
    /// 
    [EditorBrowsable(EditorBrowsableState.Never)] 
    [Obsolete("Use of this property is not recommended because it is no longer useful. http://go.microsoft.com/fwlink/?linkid=14202")]
    protected virtual int AutoHandlers { 
        get { return 0;} 
        set {}
    } 

    internal override TemplateControl GetTemplateControl() {
        return this;
    } 

    internal void HookUpAutomaticHandlers() { 
        // Do nothing if auto-events are not supported 
        if (!SupportAutoEvents) {
            return; 
        }

        // Get the event list for this Type from our cache, if possible
        object o = _eventListCache[GetType()]; 

        IDictionary dictionary = null; 
 
        // Try to find what handlers are implemented if not tried before
        if (o == null) { 
            lock (_lockObject) {

                // Try the cache again, in case another thread took care of it
                o = _eventListCache[GetType()]; 

                if (o == null) { 
                    dictionary = new ListDictionary(); 

                    GetDelegateInformation(dictionary); 

                    // Cannot find any known handlers.
                    if (dictionary.Count == 0) {
                        o = _emptyEventSingleton; 
                    }
                    else { 
                        o = dictionary; 
                    }
 
                    // Cache it for next time
                    _eventListCache[GetType()] = o;
                }
            } 
        }
 
        // Don't do any thing if no known handlers are found. 
        if (o == _emptyEventSingleton) {
            return; 
        }

        dictionary = (IDictionary)o;
 
        foreach (string key in dictionary.Keys) {
            EventMethodInfo info = (EventMethodInfo)dictionary[key]; 
 
            Debug.Assert(_eventObjects[key] != null);
 
            bool eventExists = false;
            MethodInfo methodInfo = info.MethodInfo;

            Delegate eventDelegates = Events[_eventObjects[key]]; 
            if (eventDelegates != null) {
                foreach (Delegate eventDelegate in eventDelegates.GetInvocationList()) { 
                    // Ignore if this method is already added to the events list. 
                    if (eventDelegate.Method.Equals(methodInfo)) {
                        eventExists = true; 
                        break;
                    }
                }
            } 

            if (!eventExists) { 
                // Create a new Calli delegate proxy 
                IntPtr functionPtr = methodInfo.MethodHandle.GetFunctionPointer();
                EventHandler handler = (new CalliEventHandlerDelegateProxy(this, functionPtr, info.IsArgless)).Handler; 

                // Adds the delegate to events list.
                Events.AddHandler(_eventObjects[key], handler);
            } 
        }
    } 
 
    private void GetDelegateInformation(IDictionary dictionary) {
        if (HttpRuntime.IsFullTrust) { 
            GetDelegateInformationWithNoAssert(dictionary);
        }
        else {
            GetDelegateInformationWithAssert(dictionary); 
        }
    } 
 
    // Make sure we have reflection permission to discover the handlers (ASURT 105965)
    [ReflectionPermission(SecurityAction.Assert, Flags = ReflectionPermissionFlag.MemberAccess)] 
    private void GetDelegateInformationWithAssert(IDictionary dictionary) {
        GetDelegateInformationWithNoAssert(dictionary);
    }
 
    private void GetDelegateInformationWithNoAssert(IDictionary dictionary) {
        if (this is Page) { 
            GetDelegateInformationFromMethod(_pagePreInitEventName, dictionary); 
            GetDelegateInformationFromMethod(_pagePreLoadEventName, dictionary);
            GetDelegateInformationFromMethod(_pageLoadCompleteEventName, dictionary); 
            GetDelegateInformationFromMethod(_pagePreRenderCompleteEventName, dictionary);
            GetDelegateInformationFromMethod(_pageInitCompleteEventName, dictionary);
            GetDelegateInformationFromMethod(_pageSaveStateCompleteEventName, dictionary);
        } 

        GetDelegateInformationFromMethod(_pageInitEventName, dictionary); 
        GetDelegateInformationFromMethod(_pageLoadEventName, dictionary); 
        GetDelegateInformationFromMethod(_pageDataBindEventName, dictionary);
        GetDelegateInformationFromMethod(_pagePreRenderEventName, dictionary); 
        GetDelegateInformationFromMethod(_pageUnloadEventName, dictionary);
        GetDelegateInformationFromMethod(_pageErrorEventName, dictionary);

        if (!GetDelegateInformationFromMethod(_pageAbortTransactionEventName, dictionary)) { 
            GetDelegateInformationFromMethod(_onTransactionAbortEventName, dictionary);
        } 
 
        if (!GetDelegateInformationFromMethod(_pageCommitTransactionEventName, dictionary)) {
            GetDelegateInformationFromMethod(_onTransactionCommitEventName, dictionary); 
        }
    }

    private bool GetDelegateInformationFromMethod(string methodName, IDictionary dictionary) { 

        // First, try to get a delegate to the two parameter handler 
        EventHandler e = (EventHandler)Delegate.CreateDelegate(typeof(EventHandler), this, 
            methodName, true /*ignoreCase*/, false /*throwOnBindFailure*/);
 
        if (e != null) {
            dictionary[methodName] = new EventMethodInfo(e.Method, false);
            return true;
        } 

        // If there isn't one, try the argless one 
        VoidMethod vm = (VoidMethod)Delegate.CreateDelegate(typeof(VoidMethod), this, 
            methodName, true /*ignoreCase*/, false /*throwOnBindFailure*/);
        if (vm != null) { 
            dictionary[methodName] = new EventMethodInfo(vm.Method, true);
            return true;
        }
 
        return false;
    } 
 

    ///  
    /// Obtains a  object from a user control file.
    /// 
    public Control LoadControl(string virtualPath) {
 
        return LoadControl(VirtualPath.Create(virtualPath));
    } 
 
    internal Control LoadControl(VirtualPath virtualPath) {
 
        // If it's relative, make it *app* relative.  Treat is as relative to this
        // user control (ASURT 55513)
        virtualPath = VirtualPath.Combine(this.TemplateControlVirtualDirectory, virtualPath);
 
        // Process the user control and get its BuildResult
        BuildResult result = BuildManager.GetVPathBuildResult(Context, virtualPath); 
 
        return LoadControl((IWebObjectFactory)result, virtualPath, null /*Type*/, null /*parameters*/);
    } 

    // Make sure we have reflection permission to use GetMethod below (ASURT 106196)
    [ReflectionPermission(SecurityAction.Assert, Flags=ReflectionPermissionFlag.MemberAccess)]
    private void AddStackContextToHashCode(HashCodeCombiner combinedHashCode) { 

        StackTrace st = new StackTrace(); 
 
        // First, skip all the stack frames that are in the TemplateControl class, as
        // they are irrelevant to the hash.  Start the search at 2 since we know for sure 
        // that this method and its caller are in TemplateControl.
        int startingUserFrame = 2;
        for (; ; startingUserFrame++) {
            StackFrame f = st.GetFrame(startingUserFrame); 
            if (f.GetMethod().DeclaringType != typeof(TemplateControl)) {
                break; 
            } 
        }
 
        // Get a cache key based on the top two items of the caller's stack.
        // It's not guaranteed unique, but for all common cases, it will be
        for (int i = startingUserFrame; i < startingUserFrame + 2; i++) {
            StackFrame f = st.GetFrame(i); 

            MethodBase m = f.GetMethod(); 
            combinedHashCode.AddObject(m.DeclaringType.AssemblyQualifiedName); 
            combinedHashCode.AddObject(m.Name);
            combinedHashCode.AddObject(f.GetNativeOffset()); 
        }
    }

 
    public Control LoadControl(Type t, object[] parameters) {
 
        return LoadControl(null /*IWebObjectFactory*/, null /*virtualPath*/, t, parameters); 
    }
 

    private Control LoadControl(IWebObjectFactory objectFactory, VirtualPath virtualPath, Type t, object[] parameters) {

        // Make sure we get an object factory or a type, but not both 
        Debug.Assert((objectFactory == null) != (t == null));
 
        BuildResultCompiledType compiledUCResult = null; 
        BuildResultNoCompileUserControl noCompileUCResult = null;
 
        if (objectFactory != null) {
            // It can be a compiled or no-compile user control
            compiledUCResult = objectFactory as BuildResultCompiledType;
            if (compiledUCResult != null) { 
                t = compiledUCResult.ResultType;
                Debug.Assert(t != null); 
 
                // Make sure it's a user control (VSWhidbey 428718)
                Util.CheckAssignableType(typeof(UserControl), t); 
            }
            else {
                noCompileUCResult = (BuildResultNoCompileUserControl)objectFactory;
                Debug.Assert(noCompileUCResult != null); 
            }
        } 
        else { 
            // Make sure the type has the correct base class (ASURT 123677)
            if (t != null) 
                Util.CheckAssignableType(typeof(Control), t);
        }

        PartialCachingAttribute cacheAttrib; 

        // Check if the user control has a PartialCachingAttribute attribute 
        if (t != null) { 
            cacheAttrib = (PartialCachingAttribute)
                TypeDescriptor.GetAttributes(t)[typeof(PartialCachingAttribute)]; 
        }
        else {
            cacheAttrib = noCompileUCResult.CachingAttribute;
        } 

        if (cacheAttrib == null) { 
            // The control is not cached.  Just create it. 
            Control c;
            if (objectFactory != null) { 
                c = (Control) objectFactory.CreateInstance();
            }
            else {
                c = (Control) HttpRuntime.CreatePublicInstance(t, parameters); 
            }
 
            // If it's a user control, do some extra initialization 
            UserControl uc = c as UserControl;
            if (uc != null) { 
                Debug.Assert(virtualPath != null);
                if (virtualPath != null)
                    uc.TemplateControlVirtualPath = virtualPath;
                uc.InitializeAsUserControl(Page); 
            }
 
            return c; 
        }
 
        HashCodeCombiner combinedHashCode = new HashCodeCombiner();

        // Start by adding the type or object factory of the user control to the hash.
        // This guarantees that two unrelated user controls don't share the same cached data. 
        if (objectFactory != null) {
            combinedHashCode.AddObject(objectFactory); 
        } 
        else {
            combinedHashCode.AddObject(t); 
        }

        // If it's not shared, add some stack frames to the hash
        if (!cacheAttrib.Shared) { 
            AddStackContextToHashCode(combinedHashCode);
        } 
 
        string cacheKey = combinedHashCode.CombinedHashString;
 
        // Wrap it to allow it to be cached
        return new PartialCachingControl(objectFactory, t, cacheAttrib, "_" + cacheKey, parameters);
    }
 
    // Class that implements the templates returned by LoadTemplate (ASURT 94138)
    internal class SimpleTemplate : ITemplate { 
        private IWebObjectFactory _objectFactory; 

        internal SimpleTemplate(ITypedWebObjectFactory objectFactory) { 

            // Make sure it's a user control (VSWhidbey 428718)
            Util.CheckAssignableType(typeof(UserControl), objectFactory.InstantiatedType);
 
            _objectFactory = objectFactory;
        } 
 
        public virtual void InstantiateIn(Control control) {
            UserControl uc = (UserControl)_objectFactory.CreateInstance(); 

            uc.InitializeAsUserControl(control.Page);

            control.Controls.Add(uc); 
        }
    } 
 

    ///  
    ///    
    ///       Obtains an instance of the  interface from an
    ///       external file.
    ///     
    /// 
    public ITemplate LoadTemplate(string virtualPath) { 
        return LoadTemplate(VirtualPath.Create(virtualPath)); 
    }
 
    internal ITemplate LoadTemplate(VirtualPath virtualPath) {

        // If it's relative, make it *app* relative.  Treat is as relative to this
        // user control (ASURT 55513) 
        virtualPath = VirtualPath.Combine(TemplateControlVirtualDirectory, virtualPath);
 
        // Compile the declarative template and get its object factory 
        ITypedWebObjectFactory objectFactory = (ITypedWebObjectFactory)BuildManager.GetVPathBuildResult(
            Context, virtualPath); 

        return new SimpleTemplate(objectFactory);
    }
 

    ///  
    ///     Parse the input string into a Control.  Looks for the first control 
    ///    in the input.  Returns null if none is found.
    ///  
    public Control ParseControl(string content) {
        return ParseControl(content, true);
    }
 
    public Control ParseControl(string content, bool ignoreParserFilter) {
        return TemplateParser.ParseControl(content, VirtualPath.Create(AppRelativeVirtualPath), ignoreParserFilter); 
    } 

#if NOTYET 

    /// 
    ///     Parse the input string into an ITemplate.
    ///  
    internal ITemplate ParseTemplate(string content) {
        return TemplateParser.ParseTemplate(content, AppRelativeTemplateSourceDirectory); 
    } 
#endif
 
    /// 
    /// Used by simplified databinding methods to ensure they can only be called when the control is on a page.
    /// 
    private void CheckPageExists() { 
        if (Page == null) {
            throw new InvalidOperationException(SR.GetString(SR.TemplateControl_DataBindingRequiresPage)); 
        } 
    }
 

    /// 
    /// Simplified databinding Eval() method. This method uses the current data item to evaluate an expression using DataBinder.Eval().
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'. 
    /// If the data item is not found, an exception is thrown.
    ///  
    protected internal object Eval(string expression) { 
        CheckPageExists();
        return DataBinder.Eval(Page.GetDataItem(), expression); 
    }


    ///  
    /// Simplified databinding Eval() method with a format expression. This method uses the current data item to evaluate an expression using DataBinder.Eval().
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'. 
    /// If the data item is not found, an exception is thrown. 
    /// 
    protected internal string Eval(string expression, string format) { 
        CheckPageExists();
        return DataBinder.Eval(Page.GetDataItem(), expression, format);
    }
 

    ///  
    /// Simplified databinding XPath() method. This method uses the current data item to evaluate an XPath expression using XPathBinder.Eval(). 
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'.
    /// If the data item is not found, an exception is thrown. 
    /// 
    protected internal object XPath(string xPathExpression) {
        CheckPageExists();
        return XPathBinder.Eval(Page.GetDataItem(), xPathExpression); 
    }
 
    ///  
    /// Simplified databinding XPath() method. This method uses the current data item and a namespace resolver
    /// to evaluate an XPath expression using XPathBinder.Eval(). 
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'.
    /// If the data item is not found, an exception is thrown.
    /// 
    protected internal object XPath(string xPathExpression, IXmlNamespaceResolver resolver) { 
        CheckPageExists();
        return XPathBinder.Eval(Page.GetDataItem(), xPathExpression, resolver); 
    } 

 
    /// 
    /// Simplified databinding XPath() method with a format expression. This method uses the current data item to evaluate an XPath expression using XPathBinder.Eval().
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'.
    /// If the data item is not found, an exception is thrown. 
    /// 
    protected internal string XPath(string xPathExpression, string format) { 
        CheckPageExists(); 
        return XPathBinder.Eval(Page.GetDataItem(), xPathExpression, format);
    } 

    /// 
    /// Simplified databinding XPath() method with a format expression. This method uses the current data item and a namespace resolver
    /// to evaluate an XPath expression using XPathBinder.Eval(). 
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'.
    /// If the data item is not found, an exception is thrown. 
    ///  
    protected internal string XPath(string xPathExpression, string format, IXmlNamespaceResolver resolver) {
        CheckPageExists(); 
        return XPathBinder.Eval(Page.GetDataItem(), xPathExpression, format, resolver);
    }

 
    /// 
    /// Simplified databinding XPathSelect() method. This method uses the current data item to evaluate an XPath expression that returns a node list using XPathBinder.Select(). 
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'. 
    /// If the data item is not found, an exception is thrown.
    ///  
    protected internal IEnumerable XPathSelect(string xPathExpression) {
        CheckPageExists();
        return XPathBinder.Select(Page.GetDataItem(), xPathExpression);
    } 

    ///  
    /// Simplified databinding XPathSelect() method. This method uses the current data item and a namespace resolver 
    /// to evaluate an XPath expression that returns a node list using XPathBinder.Select().
    /// The data item is retrieved using either the IDataItemContainer interface or by looking for a property called 'DataItem'. 
    /// If the data item is not found, an exception is thrown.
    /// 
    protected internal IEnumerable XPathSelect(string xPathExpression, IXmlNamespaceResolver resolver) {
        CheckPageExists(); 
        return XPathBinder.Select(Page.GetDataItem(), xPathExpression, resolver);
    } 
 

    ///  
    /// Return a Page-level resource object
    /// 
    protected object GetLocalResourceObject(string resourceKey) {
 
        // Cache the resource provider in the template control, so that if a Page needs to call
        // this multiple times, we don't need to call ResourceExpressionBuilder.GetLocalResourceProvider 
        // every time. 
        if (_resourceProvider == null)
            _resourceProvider = ResourceExpressionBuilder.GetLocalResourceProvider(this); 

        return ResourceExpressionBuilder.GetResourceObject(_resourceProvider, resourceKey, null /*culture*/);
    }
 
    protected object GetLocalResourceObject(string resourceKey, Type objType, string propName) {
 
        // Cache the resource provider in the template control, so that if a Page needs to call 
        // this multiple times, we don't need to call ResourceExpressionBuilder.GetLocalResourceProvider
        // every time. 
        if (_resourceProvider == null)
            _resourceProvider = ResourceExpressionBuilder.GetLocalResourceProvider(this);

        return ResourceExpressionBuilder.GetResourceObject(_resourceProvider, 
            resourceKey, null /*culture*/, objType, propName);
    } 
 

    ///  
    /// Return an App-level resource object
    /// 
    protected object GetGlobalResourceObject(string className, string resourceKey) {
        return ResourceExpressionBuilder.GetGlobalResourceObject(className, resourceKey, null, null, null); 
    }
 
    protected object GetGlobalResourceObject(string className, string resourceKey, Type objType, string propName) { 
        return ResourceExpressionBuilder.GetGlobalResourceObject(className, resourceKey, objType, propName, null);
    } 

    #region IFilterResolutionService

    ///  
    bool IFilterResolutionService.EvaluateFilter(string filterName) {
        return TestDeviceFilter(filterName); 
    } 

 
    /// 
    int IFilterResolutionService.CompareFilters(string filter1, string filter2) {
        return BrowserCapabilitiesCompiler.BrowserCapabilitiesFactory.CompareFilters(filter1, filter2);
    } 
    #endregion
 
    // Internal helper class for storing the event info 
    private class EventMethodInfo {
        private bool _isArgless; 
        private MethodInfo _methodInfo;

        internal EventMethodInfo(MethodInfo methodInfo, bool isArgless) {
            _isArgless = isArgless; 
            _methodInfo = methodInfo;
        } 
 
        internal bool IsArgless { get { return _isArgless; } }
        internal MethodInfo MethodInfo { get { return _methodInfo; } } 
    }
}
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK