preparational changes for adding configurable control and response caching (SPRNET-972)

This commit is contained in:
eeichinger
2008-07-11 17:08:01 +00:00
parent 5e8a094389
commit 6622f0ed4d
11 changed files with 128 additions and 39 deletions

View File

@@ -187,6 +187,13 @@ namespace Spring.Util
}
}
private static readonly SafeField ControlsArrayField = new SafeField(typeof(ControlCollection).GetField("_controls", BindingFlags.Instance|BindingFlags.NonPublic));
public void SetControlAt(Control control, int index)
{
Control[] controls = (Control[]) ControlsArrayField.GetValue(this.Controls);
controls[index] = control;
}
#if NET_2_0
private delegate ControlCollection GetControlsDelegate(Control target);
private delegate void SetControlsDelegate(Control target, ControlCollection controls);
@@ -297,4 +304,4 @@ namespace Spring.Util
}
#endif
}
}
}

View File

@@ -18,8 +18,10 @@
#region Imports
using System;
using System.Collections;
using System.Web.UI;
using Common.Logging;
using Spring.Context;
using Spring.Util;
@@ -33,6 +35,17 @@ namespace Spring.Web.Support
/// <author>Erich Eichinger</author>
internal sealed class ControlInterceptor
{
private class NoOpInterceptionStrategy : IInterceptionStrategy
{
private ILog Log = LogManager.GetLogger(typeof(NoOpInterceptionStrategy));
public bool Intercept(IApplicationContext defaultApplicationContext, ControlAccessor ctlAccessor,
ControlCollectionAccessor ctlColAccessor)
{
return true;
}
}
/// <summary>
/// Holds all available interception strategies
/// </summary>
@@ -41,7 +54,12 @@ namespace Spring.Web.Support
new InterceptControlCollectionStrategy()
, new InterceptControlCollectionOwnerStrategy()
};
/// <summary>
/// The last resort interception strategy...
/// </summary>
private static readonly IInterceptionStrategy s_noopInterceptionStrategy = new NoOpInterceptionStrategy();
/// <summary>
/// Holds a control.GetType()->IInterceptionStrategy table.
/// </summary>
@@ -102,12 +120,20 @@ namespace Spring.Web.Support
else
{
// probe for a strategy
bool bOk = false;
for(int i=0;i<s_availableInterceptionStrategies.Length;i++)
{
bool bOk = s_availableInterceptionStrategies[i].Intercept(defaultApplicationContext, ctlAccessor, ctlColAccessor);
strategy = s_availableInterceptionStrategies[i];
bOk = strategy.Intercept(defaultApplicationContext, ctlAccessor, ctlColAccessor);
if (bOk) break;
}
if (!bOk)
{
LogManager.GetLogger(typeof(ControlInterceptor)).Warn(string.Format("dependency injection not supported for control type {0}", ctlAccessor.GetTarget().GetType()));
strategy = s_noopInterceptionStrategy;
}
lock(s_cachedInterceptionStrategies)
{
s_cachedInterceptionStrategies[control.GetType()] = strategy;
@@ -130,4 +156,4 @@ namespace Spring.Web.Support
return false;
}
}
}
}

View File

@@ -48,7 +48,7 @@ namespace Spring.Web.Support
/// <summary>
/// Holds a reference to the static(!) callback-method to be used during generation of intercepted ControlCollection-Types
/// </summary>
private delegate void InjectDependenciesCallbackHandler(IApplicationContext defaultApplicationContext, Control control);
private delegate Control InjectDependenciesCallbackHandler(IApplicationContext defaultApplicationContext, Control control);
/// <summary>
/// The list of methods to be intercepted for a ControlCollection
@@ -216,4 +216,4 @@ namespace Spring.Web.Support
return interceptedCollectionType;
}
}
}
}

View File

@@ -18,6 +18,7 @@
#region Imports
using System;
using System.Reflection;
using System.Reflection.Emit;
using Spring.Proxy;
@@ -73,10 +74,19 @@ namespace Spring.Web.Support
ParameterInfo[] callbackParams = _callbackMethod.GetParameters();
ParameterInfo[] paramArray = method.GetParameters();
Type returnType = _callbackMethod.ReturnType;
int replaceArgumentIndex = -1;
for (int j = 1; j < callbackParams.Length; j++)
{
for (int i = 0; i < paramArray.Length; i++)
{
// remember the parameter to assign the value returned from the callback to
if (paramArray[i].ParameterType == returnType)
{
replaceArgumentIndex = i;
}
if (paramArray[i].ParameterType == callbackParams[j].ParameterType)
{
il.Emit(OpCodes.Ldarg_S, i + 1);
@@ -87,7 +97,12 @@ namespace Spring.Web.Support
// invoke static(!) callback
il.EmitCall(OpCodes.Call, _callbackMethod, null);
// if callback has a result, store the result back into the first matching argument
if (replaceArgumentIndex > -1)
{
il.Emit(OpCodes.Starg_S, (byte)replaceArgumentIndex+1);
}
return;
}
}
}
}

View File

@@ -63,8 +63,11 @@ namespace Spring.Web.Support
protected override void AddedControl(Control control, int index)
{
// do DI
WebDependencyInjectionUtils.InjectDependenciesRecursive(_defaultApplicationContext, control);
Control configuredControl = WebDependencyInjectionUtils.InjectDependenciesRecursive(_defaultApplicationContext, control);
if (configuredControl != control)
{
_targetControl.SetControlAt( configuredControl, index );
}
_targetControl.AddedControl(control, index);
}
@@ -77,4 +80,4 @@ namespace Spring.Web.Support
_targetControl.RemovedControl(control);
}
}
}
}

View File

@@ -36,22 +36,23 @@ namespace Spring.Web.Support
/// </summary>
/// <param name="applicationContext">ApplicationContext to be used</param>
/// <param name="control">Control to inject dependencies into.</param>
public static void InjectDependenciesRecursive(IApplicationContext applicationContext, Control control)
public static Control InjectDependenciesRecursive(IApplicationContext applicationContext, Control control)
{
if (applicationContext != null)
{
InjectDependenciesRecursiveInternal(applicationContext, control);
control = InjectDependenciesRecursiveInternal(applicationContext, control);
}
return control;
}
private static void InjectDependenciesRecursiveInternal(IApplicationContext appContext, Control control)
private static Control InjectDependenciesRecursiveInternal(IApplicationContext appContext, Control control)
{
if (control is LiteralControl) return; // nothing to do
if (control is LiteralControl) return control; // nothing to do
ISupportsWebDependencyInjection diControl = control as ISupportsWebDependencyInjection;
if (diControl != null && diControl.DefaultApplicationContext != null)
{
return; // nothing to do anymore - control cares for its children
return control; // nothing to do anymore - control cares for itself and its children
}
// "intercept" Control to make it DI-aware
@@ -72,7 +73,7 @@ namespace Spring.Web.Support
}
// inject dependencies using control's context
appContextToUse.ConfigureObject(control, control.GetType().FullName);
control = (Control)appContextToUse.ConfigureObject(control, control.GetType().FullName);
// and now go for control's children
if (control.HasControls())
@@ -82,12 +83,18 @@ namespace Spring.Web.Support
for (int i = 0; i < childCount; i++)
{
Control c = childControls[i];
if (!(c is LiteralControl))
if (c is LiteralControl) continue;
Control configuredControl = InjectDependenciesRecursiveInternal(appContext, c);
if (configuredControl != c)
{
InjectDependenciesRecursiveInternal(appContext, c);
ControlAccessor ac = new ControlAccessor(c.Parent);
ac.SetControlAt(configuredControl, i);
}
}
}
return control;
}
/// <summary>
@@ -109,4 +116,4 @@ namespace Spring.Web.Support
}
}
}
}
}

View File

@@ -161,7 +161,7 @@ namespace Spring.Web.UI.Controls
if (!_suppressDependencyInjection
&& _defaultApplicationContext != null)
{
WebDependencyInjectionUtils.InjectDependenciesRecursive(_defaultApplicationContext, control);
control = WebDependencyInjectionUtils.InjectDependenciesRecursive(_defaultApplicationContext, control);
}
base.AddedControl(control, index);
}
@@ -187,4 +187,4 @@ namespace Spring.Web.UI.Controls
#endregion Dependency Injection Support
}
}
}

View File

@@ -178,10 +178,10 @@ namespace Spring.Web.UI
/// <returns>
/// Returns the specified <see langword="UserControl"/> object, with dependencies injected.
/// </returns>
protected new Control LoadControl(string virtualPath)
protected virtual new Control LoadControl(string virtualPath)
{
Control control = base.LoadControl(virtualPath);
WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext,control);
control = WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext,control);
return control;
}
@@ -194,10 +194,10 @@ namespace Spring.Web.UI
/// <returns>
/// Returns the specified <see langword="UserControl"/> object, with dependencies injected.
/// </returns>
protected new Control LoadControl( Type t, params object[] parameters)
protected virtual new Control LoadControl( Type t, params object[] parameters)
{
Control control = base.LoadControl( t, parameters );
WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext,control);
control = WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext,control);
return control;
}
@@ -498,7 +498,7 @@ namespace Spring.Web.UI
/// </summary>
protected override void AddedControl(Control control,int index)
{
WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext,control);
control = WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext,control);
base.AddedControl(control,index);
}
@@ -508,4 +508,4 @@ namespace Spring.Web.UI
#endregion
#endif
}
}

View File

@@ -540,10 +540,10 @@ namespace Spring.Web.UI
/// <returns>
/// Returns the specified <see langword="UserControl"/> object, with dependencies injected.
/// </returns>
protected new Control LoadControl(string virtualPath)
protected virtual new Control LoadControl(string virtualPath)
{
Control control = base.LoadControl(virtualPath);
WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext, control);
control = WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext, control);
return control;
}
@@ -557,10 +557,10 @@ namespace Spring.Web.UI
/// <returns>
/// Returns the specified <see langword="UserControl"/> object, with dependencies injected.
/// </returns>
protected new Control LoadControl(Type t, params object[] parameters)
protected virtual new Control LoadControl(Type t, params object[] parameters)
{
Control control = base.LoadControl(t, parameters);
WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext, control);
control = WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext, control);
return control;
}
#endif
@@ -1656,11 +1656,11 @@ namespace Spring.Web.UI
/// </summary>
protected override void AddedControl(Control control, int index)
{
WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext, control);
control = WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext, control);
base.AddedControl(control, index);
}
#endregion Dependency Injection Support
}
}
}

View File

@@ -280,10 +280,10 @@ namespace Spring.Web.UI
/// <returns>
/// Returns the specified <see langword="UserControl"/> object, with dependencies injected.
/// </returns>
protected new Control LoadControl(string virtualPath)
protected virtual new Control LoadControl(string virtualPath)
{
Control control = base.LoadControl(virtualPath);
WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext, control);
control = WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext, control);
return control;
}
@@ -297,10 +297,10 @@ namespace Spring.Web.UI
/// <returns>
/// Returns the specified <see langword="UserControl"/> object, with dependencies injected.
/// </returns>
protected new Control LoadControl( Type t, params object[] parameters)
protected virtual new Control LoadControl( Type t, params object[] parameters)
{
Control control = base.LoadControl( t, parameters );
WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext, control);
control = WebDependencyInjectionUtils.InjectDependenciesRecursive(defaultApplicationContext, control);
return control;
}
#endif
@@ -1062,4 +1062,4 @@ namespace Spring.Web.UI
#endregion Dependency Injection Support
}
}
}

View File

@@ -292,4 +292,35 @@ namespace Spring.Util
}
#endregion Test Support Classes
}
#region DI Templates // look at them using reflector
internal class DIControlCollection : ControlCollection, ISupportsWebDependencyInjection
{
private IApplicationContext _defaultApplicationContext;
public DIControlCollection(Control owner) : base(owner)
{
}
IApplicationContext ISupportsWebDependencyInjection.DefaultApplicationContext
{
get { return _defaultApplicationContext; }
set { _defaultApplicationContext = value; }
}
public override void Add(Control child)
{
child = WebDependencyInjectionUtils.InjectDependenciesRecursive(_defaultApplicationContext, child);
base.Add(child);
}
public override void AddAt(int index, Control child)
{
child = WebDependencyInjectionUtils.InjectDependenciesRecursive(_defaultApplicationContext, child);
base.AddAt(index, child);
}
}
#endregion
}