using System.Xml;
using vmw.common;
using System.Web.Util;
+using System.Collections.Generic;
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_DataBind",
"Page_PreRender",
"Page_Disposed",
- "Page_Error",
"Page_Unload",
+ "Page_Error",
"Page_AbortTransaction",
"Page_CommitTransaction" };
+ static readonly object [] EventKeys = {
+ Control.InitEvent,
+#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
+ };
+
+ enum LifeCycleEvent
+ {
+ Init,
+#if NET_2_0
+ PreInit,
+ PreLoad,
+ LoadComplete,
+ PreRenderComplete,
+ SaveStateComplete,
+ InitComplete,
+#endif
+ Load,
+ DataBinding,
+ PreRender,
+ Disposed,
+ Unload,
+ Error,
+ AbortTransaction,
+ CommitTransaction
+ }
+
const BindingFlags bflags = BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance;
- static readonly Type [] NoParams = new Type [0];
- private static string hashTableMutex = "lock"; //used to sync access ResourceHash property
- private byte [] GetResourceBytes (Type type)
+ byte [] GetResourceBytes (Type type)
{
Hashtable table = (Hashtable) AppDomain.CurrentDomain.GetData ("TemplateControl.RES_BYTES");
if (table == null) {
}
return (byte []) table [type];
}
- private void SetResourceBytes (Type type, byte [] bytes)
+ void SetResourceBytes (Type type, byte [] bytes)
{
Hashtable table = (Hashtable) AppDomain.CurrentDomain.GetData ("TemplateControl.RES_BYTES");
if (table == null) {
return;
}
- private Hashtable ResourceHash
+ Hashtable ResourceHash
{
get
{
}
}
- private string CachedString (Type type, int offset, int size)
+ string CachedString (Type type, int offset, int size)
{
CacheKey key = new CacheKey (type, offset, size);
sealed class EventMethodMap
{
- public EventMethodMap (EventInfo Event, MethodInfo Method, bool NoParameters)
+ public EventMethodMap (LifeCycleEvent EventKeyIndex, MethodInfo Method, bool NoParameters)
{
- this.Event = Event;
+ this.EventKeyIndex = EventKeyIndex;
this.Method = Method;
this.NoParameters = NoParameters;
}
- public readonly EventInfo Event;
+ public readonly LifeCycleEvent EventKeyIndex;
public readonly MethodInfo Method;
public readonly bool NoParameters;
}
typeof (object),
typeof (EventArgs) };
- foreach (string methodName in methodNames) {
+ LifeCycleEvent[] _pageEvents = new LifeCycleEvent[] {
+ LifeCycleEvent.PreInit,
+ LifeCycleEvent.PreLoad,
+ LifeCycleEvent.LoadComplete,
+ LifeCycleEvent.PreRenderComplete,
+ LifeCycleEvent.SaveStateComplete,
+ LifeCycleEvent.InitComplete
+ };
+ List<LifeCycleEvent> pageEvents = new List<LifeCycleEvent>(_pageEvents);
+
+ bool isPage = Page.GetType().IsAssignableFrom(GetType());
+
+ for (int i = 0; i < methodNames.Length; i++) {
+
+ // Don't look for page-only events in non-page controls.
+ if (!isPage && pageEvents.Contains((LifeCycleEvent)i))
+ continue;
+
+ string methodName = methodNames [i];
MethodInfo method;
bool noParams = false;
Type type = GetType ();
if (method == null) {
type = GetType ();
do {
- method = type.GetMethod (methodName, bflags, null, NoParams, null);
+ method = type.GetMethod (methodName, bflags, null, Type.EmptyTypes, null);
if (method != null) {
noParams = true;
break;
if (method.ReturnType != voidType)
continue;
- int pos = methodName.IndexOf ("_");
- string eventName = methodName.Substring (pos + 1);
- EventInfo evt = GetType ().GetEvent (eventName);
- if (evt == null) {
- /* This should never happen */
- continue;
- }
-
- eventMethodList.Add (new EventMethodMap (evt, method, noParams));
-#if ONLY_1_1
- if (method.DeclaringType != type) {
- if (!method.IsPublic && !method.IsFamilyOrAssembly &&
- !method.IsFamilyAndAssembly && !method.IsFamily)
- continue;
- }
-#endif
+ eventMethodList.Add (new EventMethodMap ((LifeCycleEvent) i, method, noParams));
}
// We copy to not lock
}
foreach (EventMethodMap eventMethod in eventMethodList) {
- if (eventMethod.NoParameters) {
- NoParamsInvoker npi = new NoParamsInvoker (this, eventMethod.Method);
- eventMethod.Event.AddEventHandler (this, npi.FakeDelegate);
- }
- else {
- eventMethod.Event.AddEventHandler (this, Delegate.CreateDelegate (typeof (EventHandler), this, eventMethod.Method));
+ EventHandler handler = eventMethod.NoParameters ?
+ new NoParamsInvoker (this, eventMethod.Method).FakeDelegate :
+ (EventHandler)Delegate.CreateDelegate (typeof (EventHandler), this, eventMethod.Method);
+
+ object eventKey = EventKeys [(int) eventMethod.EventKeyIndex];
+
+ Delegate existing = Events [eventKey];
+ if (existing != null && handler.Equals(existing))
+ continue;
+
+ switch (eventMethod.EventKeyIndex) {
+ case LifeCycleEvent.Init:
+ Init += handler;
+ break;
+#if NET_2_0
+ case LifeCycleEvent.PreInit:
+ ((Page)this).PreInit += handler;
+ break;
+ case LifeCycleEvent.PreLoad:
+ ((Page) this).PreLoad += handler;
+ break;
+ case LifeCycleEvent.LoadComplete:
+ ((Page) this).LoadComplete += handler;
+ break;
+ case LifeCycleEvent.PreRenderComplete:
+ ((Page) this).PreRenderComplete += handler;
+ break;
+ case LifeCycleEvent.SaveStateComplete:
+ ((Page) this).SaveStateComplete += handler;
+ break;
+ case LifeCycleEvent.InitComplete:
+ ((Page) this).InitComplete += handler;
+ break;
+#endif
+ case LifeCycleEvent.Load:
+ Load += handler;
+ break;
+ case LifeCycleEvent.DataBinding:
+ DataBinding += handler;
+ break;
+ case LifeCycleEvent.PreRender:
+ PreRender += handler;
+ break;
+ case LifeCycleEvent.Disposed:
+ Disposed += handler;
+ break;
+ case LifeCycleEvent.Unload:
+ Unload += handler;
+ break;
+ case LifeCycleEvent.Error:
+ Error += handler;
+ break;
+ case LifeCycleEvent.AbortTransaction:
+ AbortTransaction += handler;
+ break;
+ case LifeCycleEvent.CommitTransaction:
+ CommitTransaction += handler;
+ break;
}
}
}
}
}
- sealed private class CacheKey
+ sealed class CacheKey
{
readonly Type _type;
readonly int _offset;
}
}
+ internal override TemplateControl TemplateControlInternal {
+ get { return this; }
+ }
+
protected internal object Eval (string expression)
{
return DataBinder.Eval (Page.GetDataItem (), expression);