TARGET_JVM: wireup auto events only if user did not add them manually
[mono.git] / mcs / class / System.Web / System.Web.UI / TemplateControl.jvm.cs
index 1b574fc212046a386f9f1fb915b2c2825828dbc4..6b3d588553cfc6005b89bc48e4f5c41108641aee 100644 (file)
@@ -30,6 +30,7 @@ using System.Reflection;
 using System.Web;
 using System.IO;
 using System.Web.J2EE;
+using System.Xml;
 using vmw.common;
 using System.Web.Util;
 
@@ -37,116 +38,106 @@ namespace System.Web.UI {
 
        public abstract class TemplateControl : Control, INamingContainer
        {
-               static object abortTransaction = new object ();
-               static object commitTransaction = new object ();
-               static object error = new object ();
-               static string [] methodNames = { "Page_Init",
+               static readonly object abortTransaction = new object ();
+               static readonly object commitTransaction = new object ();
+               static readonly object error = new object ();
+               static readonly string [] methodNames = { "Page_Init",
+#if NET_2_0
+                                                "Page_PreInit",
+                                                "Page_PreLoad",
+                                                "Page_LoadComplete",
+                                                "Page_PreRenderComplete",
+                                                "Page_SaveStateComplete",
+                                                "Page_InitComplete",
+#endif
                                                 "Page_Load",
                                                 "Page_DataBind",
                                                 "Page_PreRender",
                                                 "Page_Disposed",
-                                                "Page_Error",
                                                 "Page_Unload",
+                                                "Page_Error",
                                                 "Page_AbortTransaction",
                                                 "Page_CommitTransaction" };
 
+               static readonly object [] EventKeys = {
+#if NET_2_0
+                                                Page.PreInitEvent,
+                                                Page.PreLoadEvent,
+                                                Page.LoadCompleteEvent,
+                                                Page.PreRenderCompleteEvent,
+                                                Page.SaveStateCompleteEvent,
+                                                Page.InitCompleteEvent,
+#endif
+                                               Control.LoadEvent,
+                                               Control.DataBindingEvent,
+                                               Control.PreRenderEvent,
+                                               Control.DisposedEvent,
+                                               Control.UnloadEvent,
+                                               error,
+                                               abortTransaction,
+                                               commitTransaction
+               };
+
                const BindingFlags bflags = BindingFlags.Public |
-                                           BindingFlags.NonPublic |
-                                           BindingFlags.Instance;
+                                               BindingFlags.NonPublic |
+                                               BindingFlags.Instance;
 
-               private string _templateSourceDir;
-               private static string hashTableMutex = "lock"; //used to sync access ResourceHash property
-               private byte[] GetResourceBytes(Type type) {
-                       Hashtable table = (Hashtable)AppDomain.CurrentDomain.GetData("TemplateControl.RES_BYTES");
+               private byte [] GetResourceBytes (Type type)
+               {
+                       Hashtable table = (Hashtable) AppDomain.CurrentDomain.GetData ("TemplateControl.RES_BYTES");
                        if (table == null) {
                                return null;
                        }
-                       return (byte[])table[type];
+                       return (byte []) table [type];
                }
-               private void SetResourceBytes(Type type, byte[] bytes) {
-                       Hashtable table = (Hashtable)AppDomain.CurrentDomain.GetData("TemplateControl.RES_BYTES");
+               private void SetResourceBytes (Type type, byte [] bytes)
+               {
+                       Hashtable table = (Hashtable) AppDomain.CurrentDomain.GetData ("TemplateControl.RES_BYTES");
                        if (table == null) {
-                               table = new Hashtable();
-                               AppDomain.CurrentDomain.SetData("TemplateControl.RES_BYTES" , table);
+                               table = new Hashtable ();
+                               AppDomain.CurrentDomain.SetData ("TemplateControl.RES_BYTES", table);
                        }
-                       table[type] = bytes;
+                       table [type] = bytes;
                        return;
                }
 
-               private Hashtable ResourceHash {
-                       get {
-                               Hashtable table = (Hashtable)AppDomain.CurrentDomain.GetData("TemplateControl.RES_STRING");
+               private Hashtable ResourceHash
+               {
+                       get
+                       {
+                               Hashtable table = (Hashtable) AppDomain.CurrentDomain.GetData ("TemplateControl.RES_STRING");
                                if (table == null) {
-                                       table = new Hashtable();
-                                       AppDomain.CurrentDomain.SetData("TemplateControl.RES_STRING" , table);
+                                       table = new Hashtable ();
+                                       AppDomain.CurrentDomain.SetData ("TemplateControl.RES_STRING", table);
                                }
                                return table;
                        }
+                       set
+                       {
+                               AppDomain.CurrentDomain.SetData ("TemplateControl.RES_STRING", value);
+                       }
                }
 
-               private string CachedString(string filename , int offset, int size)
+               private string CachedString (Type type, int offset, int size)
                {
-                       string key = filename + offset + size;
-                       lock (hashTableMutex)
-                       {
-                               string strObj = (string)ResourceHash[key];
-                               if (strObj == null) 
-                               {
-                                       
-                                       char[] tmp = System.Text.Encoding.UTF8.GetChars(GetResourceBytes(this.GetType()) , offset , size);
-                                       strObj = new string(tmp);
-                                       ResourceHash.Add(key, strObj);
-                               }
-                       
-                               return strObj;
+                       CacheKey key = new CacheKey (type, offset, size);
+
+                       string strObj = (string) ResourceHash [key];
+                       if (strObj == null) {
+                               char [] tmp = System.Text.Encoding.UTF8.GetChars (GetResourceBytes (this.GetType ()), offset, size);
+                               strObj = new string (tmp);
+
+                               Hashtable tmpResourceHash = (Hashtable) ResourceHash.Clone ();
+                               tmpResourceHash.Add (key, strObj);
+                               ResourceHash = tmpResourceHash;
                        }
-                       
+                       return strObj;
                }
-               public virtual string TemplateSourceDirectory_Private 
+               public virtual string TemplateSourceDirectory_Private
                {
                        get { return null; }
                }
 
-               [MonoTODO]
-               // This shouldnt be there, Page.TemplateSourceDirectory must know to get 
-               // the right directory of the control.
-               public override string TemplateSourceDirectory 
-               {
-                       get {
-#if NET_2_0
-                               if (this is MasterPage)
-                                       // because MasterPage also has implementation of this property,
-                                       // but not always gets the right directory, in case where master page
-                                       // is in the root of webapp and the page that uses it is in sub folder.
-                                       return base.TemplateSourceDirectory;
-#endif
-                               int location = 0;
-                               if (_templateSourceDir == null)
-                               {
-                                       string tempSrcDir = AppRelativeTemplateSourceDirectory;
-                                       if (tempSrcDir == null && Parent != null)
-                                               tempSrcDir = Parent.TemplateSourceDirectory;
-                                       if (tempSrcDir != null && tempSrcDir.Length > 1)
-                                       {
-                                               location = tempSrcDir.IndexOf('/',1);
-                                               if (location!= -1)
-                                                       tempSrcDir = tempSrcDir.Substring(location+1);
-                                               else
-                                                       tempSrcDir = string.Empty;
-                                       }
-                                       string answer =  HttpRuntime.AppDomainAppVirtualPath;
-                                       if(tempSrcDir == null)
-                                               tempSrcDir = "";
-                                       if (tempSrcDir.StartsWith("/") || tempSrcDir.Length == 0)
-                                               _templateSourceDir =  answer + tempSrcDir;
-                                       else
-                                               _templateSourceDir = answer + "/"+ tempSrcDir;
-                               }
-                               return _templateSourceDir;
-                       }
-               }
-
-
                #region Constructor
                protected TemplateControl ()
                {
@@ -157,13 +148,15 @@ namespace System.Web.UI {
 
                #region Properties
                [EditorBrowsable (EditorBrowsableState.Never)]
-               protected virtual int AutoHandlers {
+               protected virtual int AutoHandlers
+               {
                        get { return 0; }
                        set { }
                }
 
                [EditorBrowsable (EditorBrowsableState.Never)]
-               protected virtual bool SupportAutoEvents {
+               protected virtual bool SupportAutoEvents
+               {
                        get { return true; }
                }
 
@@ -177,57 +170,105 @@ namespace System.Web.UI {
 
                [MonoTODO]
                protected LiteralControl CreateResourceBasedLiteralControl (int offset,
-                                                                                   int size,
-                                                                                   bool fAsciiOnly)
+                                                                                       int size,
+                                                                                       bool fAsciiOnly)
                {
-                       string str = CachedString(this.GetType().FullName, offset, size);
-                       return new LiteralControl(str);
+                       string str = CachedString (this.GetType (), offset, size);
+                       return new LiteralControl (str);
                }
 
-               internal void WireupAutomaticEvents ()
+               sealed class EventMethodMap
                {
-                       if (!SupportAutoEvents || !AutoEventWireup)
-                               return;
+                       public EventMethodMap (object EventKey, MethodInfo Method, bool NoParameters)
+                       {
+                               this.EventKey = EventKey;
+                               this.Method = Method;
+                               this.NoParameters = NoParameters;
+                       }
 
-                       Type type = GetType ();
-                       foreach (string methodName in methodNames) {
-                               MethodInfo method = type.GetMethod (methodName, bflags);
-                               if (method == null)
-                                       continue;
+                       public readonly object EventKey;
+                       public readonly MethodInfo Method;
+                       public readonly bool NoParameters;
+               }
 
-#if ONLY_1_1
-                               if (method.DeclaringType != type) {
-                                       if (!method.IsPublic && !method.IsFamilyOrAssembly &&
-                                           !method.IsFamilyAndAssembly && !method.IsFamily)
+               // This hashtable cashes methods and events found in user code
+               const string eventMethodCacheKey = "eventMethodCacheKey";
+               static Hashtable EventMethodCache
+               {
+                       get { return (Hashtable) AppDomain.CurrentDomain.GetData (eventMethodCacheKey); }
+                       set { AppDomain.CurrentDomain.SetData (eventMethodCacheKey, value); }
+               }
+
+               internal void WireupAutomaticEvents ()
+               {
+                       Type cacheKey = this.GetType ();
+                       Hashtable eventMethodCache = EventMethodCache;
+                       ArrayList eventMethodList = eventMethodCache == null ? null : (ArrayList) eventMethodCache [cacheKey];
+
+                       if (eventMethodList == null) {
+                               eventMethodList = new ArrayList ();
+
+                               if (!SupportAutoEvents || !AutoEventWireup)
+                                       return;
+
+                               Type thisType = typeof (TemplateControl);
+                               Type voidType = typeof (void);
+                               Type [] DefaultParams = new Type [] {
+                               typeof (object),
+                               typeof (EventArgs) };
+
+                               for (int i = 0; i < methodNames.Length; i++) {
+                                       string methodName = methodNames [i];
+                                       MethodInfo method;
+                                       bool noParams = false;
+                                       Type type = GetType ();
+                                       do {
+                                               method = type.GetMethod (methodName, bflags, null, DefaultParams, null);
+                                               if (method != null) {
+                                                       break;
+                                               }
+
+                                               type = type.BaseType;
+                                       }
+                                       while (type != thisType);
+
+                                       if (method == null) {
+                                               type = GetType ();
+                                               do {
+                                                       method = type.GetMethod (methodName, bflags, null, Type.EmptyTypes, null);
+                                                       if (method != null) {
+                                                               noParams = true;
+                                                               break;
+                                                       }
+
+                                                       type = type.BaseType;
+                                               }
+                                               while (type != thisType);
+
+                                               if (method == null)
+                                                       continue;
+                                       }
+                                       if (method.ReturnType != voidType)
                                                continue;
-                               }
-#endif
 
-                               if (method.ReturnType != typeof (void))
-                                       continue;
+                                       eventMethodList.Add (new EventMethodMap (EventKeys [i], method, noParams));
+                               }
+                               // We copy to not lock
 
-                               ParameterInfo [] parms = method.GetParameters ();
-                               int length = parms.Length;
-                               bool noParams = (length == 0);
-                               if (!noParams && (length != 2 ||
-                                   parms [0].ParameterType != typeof (object) ||
-                                   parms [1].ParameterType != typeof (EventArgs)))
-                                       continue;
+                               Hashtable newEventMethodCache = eventMethodCache == null ? new Hashtable () : (Hashtable) eventMethodCache.Clone ();
+                               newEventMethodCache [cacheKey] = eventMethodList;
+                               EventMethodCache = newEventMethodCache;
+                       }
 
-                               int pos = methodName.IndexOf ("_");
-                               string eventName = methodName.Substring (pos + 1);
-                               EventInfo evt = type.GetEvent (eventName);
-                               if (evt == null) {
-                                       /* This should never happen */
+                       foreach (EventMethodMap eventMethod in eventMethodList) {
+                               if (Events [eventMethod.EventKey] != null)
                                        continue;
+                               if (eventMethod.NoParameters) {
+                                       NoParamsInvoker npi = new NoParamsInvoker (this, eventMethod.Method);
+                                       Events.AddHandler (eventMethod.EventKey, npi.FakeDelegate);
                                }
-
-                               if (noParams) {
-                                       NoParamsInvoker npi = new NoParamsInvoker (this, methodName);
-                                       evt.AddEventHandler (this, npi.FakeDelegate);
-                               } else {
-                                       evt.AddEventHandler (this, Delegate.CreateDelegate (
-                                                       typeof (EventHandler), this, methodName));
+                               else {
+                                       Events.AddHandler (eventMethod.EventKey, Delegate.CreateDelegate (typeof (EventHandler), this, eventMethod.Method));
                                }
                        }
                }
@@ -243,12 +284,35 @@ namespace System.Web.UI {
                                throw new ArgumentNullException ("virtualPath");
 
                        string vpath = UrlUtils.Combine (TemplateSourceDirectory, virtualPath);
-                       return PageMapper.GetObjectType(vpath);
+                       return PageMapper.GetObjectType (Context, vpath);
                }
 
                public Control LoadControl (string virtualPath)
                {
-                       object control = Activator.CreateInstance (GetTypeFromControlPath (virtualPath));
+#if NET_2_0
+                       if (virtualPath == null)
+                               throw new ArgumentNullException ("virtualPath");
+#else
+                       if (virtualPath == null)
+                               throw new HttpException ("virtualPath is null");
+#endif
+                       Type type = GetTypeFromControlPath (virtualPath);
+                       return LoadControl (type, null);
+               }
+
+               public Control LoadControl (Type type, object [] parameters)
+               {
+                       object [] attrs = type.GetCustomAttributes (typeof (PartialCachingAttribute), true);
+                       if (attrs != null && attrs.Length == 1) {
+                               PartialCachingAttribute attr = (PartialCachingAttribute) attrs [0];
+                               PartialCachingControl ctrl = new PartialCachingControl (type, parameters);
+                               ctrl.VaryByParams = attr.VaryByParams;
+                               ctrl.VaryByControls = attr.VaryByControls;
+                               ctrl.VaryByCustom = attr.VaryByCustom;
+                               return ctrl;
+                       }
+
+                       object control = Activator.CreateInstance (type, parameters);
                        if (control is UserControl)
                                ((UserControl) control).InitializeAsUserControl (Page);
 
@@ -282,10 +346,16 @@ namespace System.Web.UI {
                                eh (this, e);
                }
 
-               [MonoTODO]
+               [MonoNotSupported ("Not supported")]
                public Control ParseControl (string content)
                {
-                       return null;
+                       throw new NotSupportedException ();
+               }
+
+               [MonoLimitation ("Always returns false")]
+               public virtual bool TestDeviceFilter (string filterName)
+               {
+                       return false;
                }
 
                [MonoTODO]
@@ -298,7 +368,7 @@ namespace System.Web.UI {
                [MonoTODO ("is this correct?")]
                public Object ReadStringResource ()
                {
-                       return this.GetType();
+                       return this.GetType ();
                }
 #endif
                [MonoTODO]
@@ -306,48 +376,48 @@ namespace System.Web.UI {
                protected void SetStringResourcePointer (object stringResourcePointer,
                                                         int maxResourceOffset)
                {
-                       if ( GetResourceBytes(this.GetType()) != null)
+                       if (GetResourceBytes (this.GetType ()) != null)
                                return;
 
-                       java.lang.Class c = vmw.common.TypeUtils.ToClass(stringResourcePointer);
-                       java.lang.ClassLoader  contextClassLoader = c.getClassLoader();
-                       string assemblyName = "dll.ghres";
-                       
-                       java.io.InputStream inputStream = contextClassLoader.getResourceAsStream(assemblyName);
+                       java.lang.Class c = vmw.common.TypeUtils.ToClass (stringResourcePointer);
+                       java.lang.ClassLoader contextClassLoader = c.getClassLoader ();
+
+                       //TODO:move this code to page mapper
+                       string assemblyName = PageMapper.GetAssemblyResource (Context, VirtualPathUtility.ToAbsolute (AppRelativeVirtualPath));
+                       if (assemblyName == null)
+                               throw new HttpException (404, "The requested resource (" + this.AppRelativeVirtualPath + ") is not available.");
+
+                       java.io.InputStream inputStream = contextClassLoader.getResourceAsStream (assemblyName);
+
                        System.IO.Stream strim = null;
                        if (inputStream == null) {
-                               string descPath = String.Join("/", new string[]{"assemblies", this.GetType().Assembly.GetName().Name, assemblyName});
-                               try 
-                               {
-                                       strim = new StreamReader(HttpContext.Current.Request.MapPath("/" + descPath)).BaseStream;
+                               string descPath = String.Join ("/", new string [] { "assemblies", this.GetType ().Assembly.GetName ().Name, assemblyName });
+                               try {
+                                       strim = new StreamReader (HttpContext.Current.Request.MapPath ("/" + descPath)).BaseStream;
                                }
-                               catch (Exception ex)
-                               {
-                                       throw new System.IO.IOException("couldn't open resource file:" + assemblyName, ex);
+                               catch (Exception ex) {
+                                       throw new System.IO.IOException ("couldn't open resource file:" + assemblyName, ex);
                                }
                                if (strim == null)
-                                       throw new System.IO.IOException("couldn't open resource file:" + assemblyName);
+                                       throw new System.IO.IOException ("couldn't open resource file:" + assemblyName);
                        }
 
-                       try
-                       {
+                       try {
                                if (strim == null)
-                                       strim = (System.IO.Stream)vmw.common.IOUtils.getStream(inputStream);
-                               int capacity = (int)strim.Length;
-                               byte[] resourceBytes = new byte[capacity];
-                               strim.Read(resourceBytes,0,capacity);
-                               SetResourceBytes(this.GetType(), resourceBytes);
+                                       strim = (System.IO.Stream) vmw.common.IOUtils.getStream (inputStream);
+                               int capacity = (int) strim.Length;
+                               byte [] resourceBytes = new byte [capacity];
+                               strim.Read (resourceBytes, 0, capacity);
+                               SetResourceBytes (this.GetType (), resourceBytes);
                        }
-                       catch(Exception e)
-                       {
-                               throw new HttpException("problem with dll.ghres file", e);
+                       catch (Exception e) {
+                               throw new HttpException ("problem with dll.ghres file", e);
                        }
-                       finally
-                       {
-                               if(strim != null)
-                                       strim.Close();
-                               if (inputStream != null )
-                                       inputStream.close();
+                       finally {
+                               if (strim != null)
+                                       strim.Close ();
+                               if (inputStream != null)
+                                       inputStream.close ();
                        }
                }
 
@@ -356,8 +426,8 @@ namespace System.Web.UI {
                protected void WriteUTF8ResourceString (HtmlTextWriter output, int offset,
                                                        int size, bool fAsciiOnly)
                {
-                       string str = CachedString(this.GetType().FullName, offset, size);
-                       output.Write(str);
+                       string str = CachedString (this.GetType (), offset, size);
+                       output.Write (str);
                }
 
                #endregion
@@ -365,19 +435,22 @@ namespace System.Web.UI {
                #region Events
 
                [WebSysDescription ("Raised when the user aborts a transaction.")]
-               public event EventHandler AbortTransaction {
+               public event EventHandler AbortTransaction
+               {
                        add { Events.AddHandler (abortTransaction, value); }
                        remove { Events.RemoveHandler (abortTransaction, value); }
                }
 
                [WebSysDescription ("Raised when the user initiates a transaction.")]
-               public event EventHandler CommitTransaction {
+               public event EventHandler CommitTransaction
+               {
                        add { Events.AddHandler (commitTransaction, value); }
                        remove { Events.RemoveHandler (commitTransaction, value); }
                }
 
                [WebSysDescription ("Raised when an exception occurs that cannot be handled.")]
-               public event EventHandler Error {
+               public event EventHandler Error
+               {
                        add { Events.AddHandler (error, value); }
                        remove { Events.RemoveHandler (error, value); }
                }
@@ -401,50 +474,135 @@ namespace System.Web.UI {
                        }
                }
 
+               sealed private class CacheKey
+               {
+                       readonly Type _type;
+                       readonly int _offset;
+                       readonly int _size;
+
+                       public CacheKey (Type type, int offset, int size)
+                       {
+                               _type = type;
+                               _offset = offset;
+                               _size = size;
+                       }
+
+                       public override int GetHashCode ()
+                       {
+                               return _type.GetHashCode () ^ _offset ^ _size;
+                       }
+
+                       public override bool Equals (object obj)
+                       {
+                               if (obj == null || !(obj is CacheKey))
+                                       return false;
+
+                               CacheKey key = (CacheKey) obj;
+                               return key._type == _type && key._offset == _offset && key._size == _size;
+                       }
+               }
+
 #if NET_2_0
 
-       string _appRelativeVirtualPath = null;
+               string _appRelativeVirtualPath = null;
 
-       public string AppRelativeVirtualPath
-       {
-               get { return _appRelativeVirtualPath; }
-               set
+               public string AppRelativeVirtualPath
                {
-                       if (value == null)
-                               throw new ArgumentNullException ("value");
-                       if (!UrlUtils.IsRooted (value) && !(value.Length > 0 && value[0] == '~'))
-                               throw new ArgumentException ("The path that is set is not rooted");
-                       _appRelativeVirtualPath = value;
+                       get { return _appRelativeVirtualPath; }
+                       set
+                       {
+                               if (value == null)
+                                       throw new ArgumentNullException ("value");
+                               if (!UrlUtils.IsRooted (value) && !(value.Length > 0 && value [0] == '~'))
+                                       throw new ArgumentException ("The path that is set is not rooted");
+                               _appRelativeVirtualPath = value;
+
+                               int lastSlash = _appRelativeVirtualPath.LastIndexOf ('/');
+                               AppRelativeTemplateSourceDirectory = (lastSlash > 0) ? _appRelativeVirtualPath.Substring (0, lastSlash + 1) : "~/";
+                       }
+               }
 
-                       int lastSlash = _appRelativeVirtualPath.LastIndexOf ('/');
-                       AppRelativeTemplateSourceDirectory = (lastSlash > 0) ? _appRelativeVirtualPath.Substring (0, lastSlash + 1) : "~/";
+               internal override TemplateControl TemplateControlInternal {
+                       get { return this; }
                }
-       }
 
-       protected object Eval (string expression)
-       {
-               return DataBinder.Eval (Page.GetDataItem (), expression);
-       }
+               protected internal object Eval (string expression)
+               {
+                       return DataBinder.Eval (Page.GetDataItem (), expression);
+               }
 
-       protected string Eval (string expression, string format)
-       {
-               return DataBinder.Eval (Page.GetDataItem (), expression, format);
-       }
+               protected internal string Eval (string expression, string format)
+               {
+                       return DataBinder.Eval (Page.GetDataItem (), expression, format);
+               }
 
-       protected object XPath (string xpathexpression)
-       {
-               return XPathBinder.Eval (Page.GetDataItem (), xpathexpression);
-       }
+               protected internal object XPath (string xpathexpression)
+               {
+                       return XPathBinder.Eval (Page.GetDataItem (), xpathexpression);
+               }
 
-       protected string XPath (string xpathexpression, string format)
-       {
-               return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, format);
-       }
+               protected internal object XPath (string xpathexpression, IXmlNamespaceResolver resolver)
+               {
+                       return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, null, resolver);
+               }
+
+               protected internal string XPath (string xpathexpression, string format)
+               {
+                       return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, format);
+               }
+
+               protected internal string XPath (string xpathexpression, string format, IXmlNamespaceResolver resolver)
+               {
+                       return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, format, resolver);
+               }
+
+               protected internal IEnumerable XPathSelect (string xpathexpression)
+               {
+                       return XPathBinder.Select (Page.GetDataItem (), xpathexpression);
+               }
+
+               protected internal IEnumerable XPathSelect (string xpathexpression, IXmlNamespaceResolver resolver)
+               {
+                       return XPathBinder.Select (Page.GetDataItem (), xpathexpression, resolver);
+               }
+
+               protected object GetGlobalResourceObject (string className, string resourceKey)
+               {
+                       return HttpContext.GetGlobalResourceObject (className, resourceKey);
+               }
+
+               protected object GetGlobalResourceObject (string className, string resourceKey, Type objType, string propName)
+               {
+                       return ConvertResource (GetGlobalResourceObject (className, resourceKey), objType, propName);
+               }
+
+               protected Object GetLocalResourceObject (string resourceKey)
+               {
+                       return HttpContext.GetLocalResourceObject (Context.Request.Path, resourceKey);
+               }
+
+               protected Object GetLocalResourceObject (string resourceKey, Type objType, string propName)
+               {
+                       return ConvertResource (GetLocalResourceObject (resourceKey), objType, propName);
+               }
+
+               static Object ConvertResource (Object resource, Type objType, string propName) {
+                       if (resource == null)
+                               return resource;
+
+                       PropertyDescriptor pdesc = TypeDescriptor.GetProperties (objType) [propName];
+                       if (pdesc == null)
+                               return resource;
+
+                       TypeConverter converter = pdesc.Converter;
+                       if (converter == null)
+                               return resource;
+
+                       return resource is string ?
+                               converter.ConvertFromInvariantString ((string) resource) :
+                               converter.ConvertFrom (resource);
+               }
 
-       protected IEnumerable XPathSelect (string xpathexpression)
-       {
-               return XPathBinder.Select (Page.GetDataItem (), xpathexpression);
-       }
 #endif
 
        }