Update of /cvsroot/springnet/Spring.Net/src/Spring/Spring.Web/Web/Support
In directory sc8-pr-cvs8.sourceforge.net:/tmp/cvs-serv17466/src/Spring/Spring.Web/Web/Support
Modified Files:
ControlInterceptor.cs InterceptControlCollectionStrategy.cs
SupportsWebDependencyInjectionOwnerProxy.cs
WebDependencyInjectionUtils.cs
Log Message:
SPRNET-794 - complete rework of Control interception
minor fixes to SpringAir demo
switched DynamicField implementation to using net-2.0's DynamicMethod technique
Index: ControlInterceptor.cs
===================================================================
RCS file: /cvsroot/springnet/Spring.Net/src/Spring/Spring.Web/Web/Support/ControlInterceptor.cs,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** ControlInterceptor.cs 1 Aug 2007 23:11:00 -0000 1.1
--- ControlInterceptor.cs 13 May 2008 14:22:47 -0000 1.2
***************
*** 58,61 ****
--- 58,66 ----
public static void EnsureControlIntercepted(IApplicationContext defaultApplicationContext, Control control)
{
+ if (control is LiteralControl)
+ {
+ return; // nothing more to do
+ }
+
// check control itself
if (IsDependencyInjectionAware(defaultApplicationContext, control))
Index: WebDependencyInjectionUtils.cs
===================================================================
RCS file: /cvsroot/springnet/Spring.Net/src/Spring/Spring.Web/Web/Support/WebDependencyInjectionUtils.cs,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** WebDependencyInjectionUtils.cs 3 Feb 2008 21:38:27 -0000 1.2
--- WebDependencyInjectionUtils.cs 13 May 2008 14:22:47 -0000 1.3
***************
*** 64,68 ****
// if the control is a UserControl, use ApplicationContext from it's physical location
! IApplicationContext appContextToUse = appContext;
UserControl userControl = control as UserControl;
if (userControl != null)
--- 64,68 ----
// if the control is a UserControl, use ApplicationContext from it's physical location
! IApplicationContext appContextToUse = appContext;
UserControl userControl = control as UserControl;
if (userControl != null)
***************
*** 70,74 ****
appContextToUse = GetControlApplicationContext(appContext, userControl);
}
!
// set ApplicationContext instance
if (control is IApplicationContextAware)
--- 70,74 ----
appContextToUse = GetControlApplicationContext(appContext, userControl);
}
!
// set ApplicationContext instance
if (control is IApplicationContextAware)
***************
*** 76,80 ****
((IApplicationContextAware)control).ApplicationContext = appContextToUse;
}
!
// inject dependencies using control's context
appContextToUse.ConfigureObject(control, control.GetType().FullName);
--- 76,80 ----
((IApplicationContextAware)control).ApplicationContext = appContextToUse;
}
!
// inject dependencies using control's context
appContextToUse.ConfigureObject(control, control.GetType().FullName);
***************
*** 100,104 ****
/// </summary>
/// <returns>if availabe, the control's IApplicationContext instance - defaultContext otherwise</returns>
! private static IApplicationContext GetControlApplicationContext( IApplicationContext defaultContext, Control control )
{
// use control's directory for resolving context
--- 100,104 ----
/// </summary>
/// <returns>if availabe, the control's IApplicationContext instance - defaultContext otherwise</returns>
! private static IApplicationContext GetControlApplicationContext(IApplicationContext defaultContext, Control control)
{
// use control's directory for resolving context
Index: SupportsWebDependencyInjectionOwnerProxy.cs
===================================================================
RCS file: /cvsroot/springnet/Spring.Net/src/Spring/Spring.Web/Web/Support/SupportsWebDependencyInjectionOwnerProxy.cs,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** SupportsWebDependencyInjectionOwnerProxy.cs 1 Aug 2007 23:11:01 -0000 1.1
--- SupportsWebDependencyInjectionOwnerProxy.cs 13 May 2008 14:22:47 -0000 1.2
***************
*** 37,41 ****
{
// Control Fields and Methods
! private ControlAccessor _targetControl;
private IApplicationContext _defaultApplicationContext;
--- 37,41 ----
{
// Control Fields and Methods
! private readonly ControlAccessor _targetControl;
private IApplicationContext _defaultApplicationContext;
Index: InterceptControlCollectionStrategy.cs
===================================================================
RCS file: /cvsroot/springnet/Spring.Net/src/Spring/Spring.Web/Web/Support/InterceptControlCollectionStrategy.cs,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** InterceptControlCollectionStrategy.cs 1 Aug 2007 23:11:01 -0000 1.1
--- InterceptControlCollectionStrategy.cs 13 May 2008 14:22:47 -0000 1.2
***************
*** 22,25 ****
--- 22,26 ----
using System.Collections;
using System.Reflection;
+ using System.Reflection.Emit;
using System.Web.UI;
using Spring.Context;
***************
*** 28,31 ****
--- 29,38 ----
using Spring.Web.Support;
+ #if NET_2_0
+ using System.Collections.Generic;
+ #else
+ using Spring.Reflection.Dynamic;
+ #endif
+
#endregion
***************
*** 44,48 ****
/// </summary>
private delegate void InjectDependenciesCallbackHandler(IApplicationContext defaultApplicationContext, Control control);
!
/// <summary>
/// The list of methods to be intercepted for a ControlCollection
--- 51,55 ----
/// </summary>
private delegate void InjectDependenciesCallbackHandler(IApplicationContext defaultApplicationContext, Control control);
!
/// <summary>
/// The list of methods to be intercepted for a ControlCollection
***************
*** 53,70 ****
, typeof (ControlCollection).GetMethod("AddAt", BindingFlags.Instance | BindingFlags.Public)
};
!
/// <summary>
/// Holds a table of already known intercepted ControlCollection types
/// </summary>
private static readonly Hashtable s_interceptedCollectionTypeCache = new Hashtable();
!
!
public bool Intercept(IApplicationContext defaultApplicationContext,
! ControlAccessor ctlAccessor, ControlCollectionAccessor ctlColAccessor)
{
! Type collectionType = ctlColAccessor.GetTarget().GetType();
if (collectionType.IsSealed ||
!ReflectionUtils.IsTypeVisible(collectionType, DynamicProxyManager.ASSEMBLY_NAME))
! // || (null == collectionType.GetConstructor(new Type[] {typeof (Control)}))
{
return false;
--- 60,84 ----
, typeof (ControlCollection).GetMethod("AddAt", BindingFlags.Instance | BindingFlags.Public)
};
!
/// <summary>
/// Holds a table of already known intercepted ControlCollection types
/// </summary>
private static readonly Hashtable s_interceptedCollectionTypeCache = new Hashtable();
!
! /// <summary>
! /// Intercepts the given <see cref="ControlCollection"/> by dynamically deriving
! /// the original type and let it implement <see cref="ISupportsWebDependencyInjection"/>.
! /// </summary>
! /// <param name="defaultApplicationContext">the ApplicationContext to be set on the collection instance.</param>
! /// <param name="ctlAccessor">a wrapper around the owner control instance.</param>
! /// <param name="ctlColAccessor">a wrapper around the collection instance.</param>
! /// <returns><value>true</value>, if interception was successful. <value>false</value> otherwise</returns>
public bool Intercept(IApplicationContext defaultApplicationContext,
! ControlAccessor ctlAccessor, ControlCollectionAccessor ctlColAccessor)
{
! Type collectionType = ctlColAccessor.GetTargetType();
if (collectionType.IsSealed ||
!ReflectionUtils.IsTypeVisible(collectionType, DynamicProxyManager.ASSEMBLY_NAME))
! // || (null == collectionType.GetConstructor(new Type[] {typeof (Control)}))
{
return false;
***************
*** 74,79 ****
try
{
! ControlCollection childControls = InterceptCollection(ctlColAccessor);
! ((ISupportsWebDependencyInjection) childControls).DefaultApplicationContext = defaultApplicationContext;
ctlAccessor.Controls = childControls;
}
--- 88,93 ----
try
{
! ControlCollection childControls = InterceptCollection(ctlAccessor.GetTarget(), ctlColAccessor.GetTarget() );
! ((ISupportsWebDependencyInjection)childControls).DefaultApplicationContext = defaultApplicationContext;
ctlAccessor.Controls = childControls;
}
***************
*** 86,119 ****
}
! private static ControlCollection InterceptCollection(ControlCollectionAccessor ctlColAccessor)
{
! Type interceptedCollectionType =
! GetInterceptedCollectionType(ctlColAccessor.GetTarget().GetType(),
! new InjectDependenciesCallbackHandler(WebDependencyInjectionUtils.InjectDependenciesRecursive));
! object interceptedCollection =
! Activator.CreateInstance(interceptedCollectionType, new object[] {ctlColAccessor.Owner});
! ReflectionUtils.MemberwiseCopy(ctlColAccessor.GetTarget(), interceptedCollection);
! return (ControlCollection) interceptedCollection;
}
! private static Type GetInterceptedCollectionType(Type collectionType, InjectDependenciesCallbackHandler staticCallback)
{
! Type interceptedCollectionType;
! lock(s_interceptedCollectionTypeCache)
{
! interceptedCollectionType = (Type) s_interceptedCollectionTypeCache[collectionType];
! if (interceptedCollectionType != null)
{
! return interceptedCollectionType;
}
! else
{
! SupportsWebDependencyInjectionTypeBuilder builder =
! new SupportsWebDependencyInjectionTypeBuilder(collectionType, s_collectionMethods, staticCallback.Method);
! interceptedCollectionType = builder.BuildProxyType();
! s_interceptedCollectionTypeCache[collectionType] = interceptedCollectionType;
! return interceptedCollectionType;
}
}
}
}
--- 100,219 ----
}
! private static ControlCollection InterceptCollection(Control owner, ControlCollection originalCollection)
{
! CreateControlCollectionDelegate factoryMethod = GetInterceptedCollectionFactory(owner.GetType(), originalCollection.GetType());
! ControlCollection interceptedCollection = factoryMethod(owner);
! ReflectionUtils.MemberwiseCopy(originalCollection, interceptedCollection);
! return interceptedCollection;
}
! internal static ControlCollection TryCreateCollection(Control owner)
{
! CreateControlCollectionDelegate factoryMethod = (CreateControlCollectionDelegate)s_collectionFactoryCache[owner.GetType()];
! if (factoryMethod != null)
{
! return factoryMethod(owner);
! }
! return null;
! }
!
! private delegate ControlCollection CreateControlCollectionDelegate(Control owner);
! private static readonly Hashtable s_collectionFactoryCache = new Hashtable();
!
! #if NET_2_0
! private static CreateControlCollectionDelegate GetInterceptedCollectionFactory(Type ownerType, Type collectionType)
! {
! AssertUtils.State( typeof(Control).IsAssignableFrom(ownerType), "ownerType must be of type Control" );
! AssertUtils.State( typeof(ControlCollection).IsAssignableFrom(collectionType), "collectionType must be of type ControlCollection" );
!
! CreateControlCollectionDelegate factoryMethod = (CreateControlCollectionDelegate)s_collectionFactoryCache[ownerType];
! if (factoryMethod == null)
! {
! lock (s_collectionFactoryCache)
{
! factoryMethod = (CreateControlCollectionDelegate)s_collectionFactoryCache[ownerType];
! if (factoryMethod == null)
! {
! Type interceptedCollectionType =
! GetInterceptedCollectionType(collectionType, WebDependencyInjectionUtils.InjectDependenciesRecursive);
!
! ConstructorInfo ctor =
! interceptedCollectionType.GetConstructor(new Type[] { typeof(Control) });
! DynamicMethod dm =
! new System.Reflection.Emit.DynamicMethod(string.Empty, typeof(ControlCollection),
! new Type[] { typeof(Control) });
! ILGenerator il = dm.GetILGenerator();
! il.Emit(OpCodes.Ldarg_0);
! il.Emit(OpCodes.Newobj, ctor);
! il.Emit(OpCodes.Ret);
! factoryMethod = (CreateControlCollectionDelegate)dm.CreateDelegate(typeof(CreateControlCollectionDelegate));
! s_collectionFactoryCache[ownerType] = factoryMethod;
! }
}
! }
! return factoryMethod;
! }
! #else
! private class CreateControlCollectionWrapper
! {
! private IDynamicConstructor _ctor;
!
! public CreateControlCollectionWrapper(IDynamicConstructor ctor)
! {
! _ctor = ctor;
! }
!
! public ControlCollection Create(Control owner)
! {
! return (ControlCollection) _ctor.Invoke(new object[] {owner});
! }
! }
!
! private static CreateControlCollectionDelegate GetInterceptedCollectionFactory(Type controlType, Type controlCollectionType)
! {
! AssertUtils.State( typeof(Control).IsAssignableFrom(controlType), "controlType must be of type Control" );
! AssertUtils.State( typeof(ControlCollection).IsAssignableFrom(controlCollectionType), "controlCollectionType must be of type ControlCollection" );
!
! CreateControlCollectionDelegate factoryMethod = (CreateControlCollectionDelegate)s_collectionFactoryCache[controlType];
! if (factoryMethod == null)
! {
! lock (s_collectionFactoryCache)
{
! factoryMethod = (CreateControlCollectionDelegate)s_collectionFactoryCache[controlType];
! if (factoryMethod == null)
! {
! Type interceptedCollectionType = GetInterceptedCollectionType(controlCollectionType, new InjectDependenciesCallbackHandler(WebDependencyInjectionUtils.InjectDependenciesRecursive));
!
! ConstructorInfo ctor = interceptedCollectionType.GetConstructor(new Type[] {typeof (Control)});
! IDynamicConstructor dynCtor = new SafeConstructor(ctor);
! s_collectionFactoryCache[controlType] = new CreateControlCollectionDelegate(new CreateControlCollectionWrapper(dynCtor).Create);
! }
}
}
+ return factoryMethod;
+ }
+ #endif
+
+ private static Type GetInterceptedCollectionType(Type controlCollectionType, InjectDependenciesCallbackHandler staticCallback)
+ {
+ AssertUtils.State( typeof(ControlCollection).IsAssignableFrom(controlCollectionType), "controlCollectionType must be of type ControlCollection" );
+
+ Type interceptedCollectionType = (Type)s_interceptedCollectionTypeCache[controlCollectionType];
+ if (interceptedCollectionType == null)
+ {
+ lock (s_interceptedCollectionTypeCache)
+ {
+ MethodInfo callbackMethod = staticCallback.Method;
+ AssertUtils.State(callbackMethod.IsStatic && callbackMethod.IsPublic, "staticCallback must be a public static method");
+ interceptedCollectionType = (Type)s_interceptedCollectionTypeCache[controlCollectionType];
+ if (interceptedCollectionType == null)
+ {
+ SupportsWebDependencyInjectionTypeBuilder builder = new SupportsWebDependencyInjectionTypeBuilder(controlCollectionType, s_collectionMethods, callbackMethod);
+ interceptedCollectionType = builder.BuildProxyType();
+ s_interceptedCollectionTypeCache[controlCollectionType] = interceptedCollectionType;
+ }
+ }
+ }
+ return interceptedCollectionType;
}
}
|