diff --git a/src/Spring/Spring.Web/Util/ControlAccessor.cs b/src/Spring/Spring.Web/Util/ControlAccessor.cs
index 9e710bbf..de6b5534 100644
--- a/src/Spring/Spring.Web/Util/ControlAccessor.cs
+++ b/src/Spring/Spring.Web/Util/ControlAccessor.cs
@@ -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
}
-}
\ No newline at end of file
+}
diff --git a/src/Spring/Spring.Web/Web/Support/ControlInterceptor.cs b/src/Spring/Spring.Web/Web/Support/ControlInterceptor.cs
index 2d738bd1..43ad6cf9 100644
--- a/src/Spring/Spring.Web/Web/Support/ControlInterceptor.cs
+++ b/src/Spring/Spring.Web/Web/Support/ControlInterceptor.cs
@@ -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
/// Erich Eichinger
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;
+ }
+ }
+
///
/// Holds all available interception strategies
///
@@ -41,7 +54,12 @@ namespace Spring.Web.Support
new InterceptControlCollectionStrategy()
, new InterceptControlCollectionOwnerStrategy()
};
-
+
+ ///
+ /// The last resort interception strategy...
+ ///
+ private static readonly IInterceptionStrategy s_noopInterceptionStrategy = new NoOpInterceptionStrategy();
+
///
/// Holds a control.GetType()->IInterceptionStrategy table.
///
@@ -102,12 +120,20 @@ namespace Spring.Web.Support
else
{
// probe for a strategy
+ bool bOk = false;
for(int i=0;i
/// Holds a reference to the static(!) callback-method to be used during generation of intercepted ControlCollection-Types
///
- private delegate void InjectDependenciesCallbackHandler(IApplicationContext defaultApplicationContext, Control control);
+ private delegate Control InjectDependenciesCallbackHandler(IApplicationContext defaultApplicationContext, Control control);
///
/// The list of methods to be intercepted for a ControlCollection
@@ -216,4 +216,4 @@ namespace Spring.Web.Support
return interceptedCollectionType;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Spring/Spring.Web/Web/Support/SupportsWebDependencyInjectionMethodBuilder.cs b/src/Spring/Spring.Web/Web/Support/SupportsWebDependencyInjectionMethodBuilder.cs
index 16a9ff4f..6ed9a1a1 100644
--- a/src/Spring/Spring.Web/Web/Support/SupportsWebDependencyInjectionMethodBuilder.cs
+++ b/src/Spring/Spring.Web/Web/Support/SupportsWebDependencyInjectionMethodBuilder.cs
@@ -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;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Spring/Spring.Web/Web/Support/SupportsWebDependencyInjectionOwnerProxy.cs b/src/Spring/Spring.Web/Web/Support/SupportsWebDependencyInjectionOwnerProxy.cs
index f3ea2bf3..661162bf 100644
--- a/src/Spring/Spring.Web/Web/Support/SupportsWebDependencyInjectionOwnerProxy.cs
+++ b/src/Spring/Spring.Web/Web/Support/SupportsWebDependencyInjectionOwnerProxy.cs
@@ -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);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Spring/Spring.Web/Web/Support/WebDependencyInjectionUtils.cs b/src/Spring/Spring.Web/Web/Support/WebDependencyInjectionUtils.cs
index cea2a1cb..1b86b6c2 100644
--- a/src/Spring/Spring.Web/Web/Support/WebDependencyInjectionUtils.cs
+++ b/src/Spring/Spring.Web/Web/Support/WebDependencyInjectionUtils.cs
@@ -36,22 +36,23 @@ namespace Spring.Web.Support
///
/// ApplicationContext to be used
/// Control to inject dependencies into.
- 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;
}
///
@@ -109,4 +116,4 @@ namespace Spring.Web.Support
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Spring/Spring.Web/Web/UI/Controls/Panel.cs b/src/Spring/Spring.Web/Web/UI/Controls/Panel.cs
index de2e2b10..edbd3746 100644
--- a/src/Spring/Spring.Web/Web/UI/Controls/Panel.cs
+++ b/src/Spring/Spring.Web/Web/UI/Controls/Panel.cs
@@ -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
}
-}
\ No newline at end of file
+}
diff --git a/src/Spring/Spring.Web/Web/UI/MasterPage.cs b/src/Spring/Spring.Web/Web/UI/MasterPage.cs
index 22d65b02..249a74ff 100644
--- a/src/Spring/Spring.Web/Web/UI/MasterPage.cs
+++ b/src/Spring/Spring.Web/Web/UI/MasterPage.cs
@@ -178,10 +178,10 @@ namespace Spring.Web.UI
///
/// Returns the specified object, with dependencies injected.
///
- 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 the specified object, with dependencies injected.
///
- 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
///
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
-}
\ No newline at end of file
+}
diff --git a/src/Spring/Spring.Web/Web/UI/Page.cs b/src/Spring/Spring.Web/Web/UI/Page.cs
index 9e039cd8..d4bdea23 100644
--- a/src/Spring/Spring.Web/Web/UI/Page.cs
+++ b/src/Spring/Spring.Web/Web/UI/Page.cs
@@ -540,10 +540,10 @@ namespace Spring.Web.UI
///
/// Returns the specified object, with dependencies injected.
///
- 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 the specified object, with dependencies injected.
///
- 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
///
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
}
-}
\ No newline at end of file
+}
diff --git a/src/Spring/Spring.Web/Web/UI/UserControl.cs b/src/Spring/Spring.Web/Web/UI/UserControl.cs
index a61aa6a6..c63fa430 100644
--- a/src/Spring/Spring.Web/Web/UI/UserControl.cs
+++ b/src/Spring/Spring.Web/Web/UI/UserControl.cs
@@ -280,10 +280,10 @@ namespace Spring.Web.UI
///
/// Returns the specified object, with dependencies injected.
///
- 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 the specified object, with dependencies injected.
///
- 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
}
-}
\ No newline at end of file
+}
diff --git a/test/Spring/Spring.Web.Tests/Util/ControlInterceptionTests.cs b/test/Spring/Spring.Web.Tests/Util/ControlInterceptionTests.cs
index 6428021e..1fb06a93 100644
--- a/test/Spring/Spring.Web.Tests/Util/ControlInterceptionTests.cs
+++ b/test/Spring/Spring.Web.Tests/Util/ControlInterceptionTests.cs
@@ -292,4 +292,35 @@ namespace Spring.Util
}
#endregion Test Support Classes
-}
\ No newline at end of file
+
+ #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
+}