resolved SPRNET-969
This commit is contained in:
@@ -40,7 +40,7 @@ namespace Spring.Expressions
|
||||
| BindingFlags.Instance | BindingFlags.Static
|
||||
| BindingFlags.IgnoreCase;
|
||||
|
||||
private SafeIndexer indexer;
|
||||
private SafeProperty indexer;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance
|
||||
@@ -191,7 +191,7 @@ namespace Spring.Expressions
|
||||
EvaluationContext evalContext = new EvaluationContext(context, variables);
|
||||
InitializeIndexerProperty(context, evalContext);
|
||||
|
||||
return indexer.IndexerProperty;
|
||||
return indexer.PropertyInfo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ namespace Spring.Expressions
|
||||
private void SetGenericIndexer(object context, EvaluationContext evalContext,object newValue)
|
||||
{
|
||||
object[] indices = InitializeIndexerProperty( context, evalContext );
|
||||
indexer.SetValue( context,indices,newValue );
|
||||
indexer.SetValue( context, newValue, indices );
|
||||
}
|
||||
|
||||
private object[] InitializeIndexerProperty(object context, EvaluationContext evalContext)
|
||||
@@ -281,7 +281,7 @@ namespace Spring.Expressions
|
||||
}
|
||||
else
|
||||
{
|
||||
indexer = new SafeIndexer(indexerProperty);
|
||||
indexer = new SafeProperty(indexerProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace Spring.Reflection.Dynamic
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
public class BaseDynamicMember
|
||||
{
|
||||
//#if NET_2_0
|
||||
//#else
|
||||
/// <summary>
|
||||
/// Method attributes constant.
|
||||
/// </summary>
|
||||
@@ -56,12 +58,12 @@ namespace Spring.Reflection.Dynamic
|
||||
if (targetType.IsValueType)
|
||||
{
|
||||
LocalBuilder target = il.DeclareLocal(targetType);
|
||||
#if NET_2_0
|
||||
il.Emit(OpCodes.Unbox_Any, targetType);
|
||||
#else
|
||||
//#if NET_2_0
|
||||
// il.Emit(OpCodes.Unbox_Any, targetType);
|
||||
//#else
|
||||
il.Emit(OpCodes.Unbox, targetType);
|
||||
il.Emit(OpCodes.Ldobj, targetType);
|
||||
#endif
|
||||
//#endif
|
||||
il.Emit(OpCodes.Stloc, target);
|
||||
il.Emit(OpCodes.Ldloca, target);
|
||||
}
|
||||
@@ -82,12 +84,12 @@ namespace Spring.Reflection.Dynamic
|
||||
il.Emit(OpCodes.Ldarg, argumentPosition);
|
||||
if (argumentType.IsValueType)
|
||||
{
|
||||
#if NET_2_0
|
||||
il.Emit(OpCodes.Unbox_Any, argumentType);
|
||||
#else
|
||||
//#if NET_2_0
|
||||
// il.Emit(OpCodes.Unbox_Any, argumentType);
|
||||
//#else
|
||||
il.Emit(OpCodes.Unbox, argumentType);
|
||||
il.Emit(OpCodes.Ldobj, argumentType);
|
||||
#endif
|
||||
//#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -142,5 +144,6 @@ namespace Spring.Reflection.Dynamic
|
||||
il.Emit(OpCodes.Newobj, invalidOperationException);
|
||||
il.Emit(OpCodes.Throw);
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using Spring.Util;
|
||||
@@ -62,7 +63,59 @@ namespace Spring.Reflection.Dynamic
|
||||
/// </remarks>
|
||||
public class SafeConstructor : IDynamicConstructor
|
||||
{
|
||||
private ConstructorInfo constructor;
|
||||
private ConstructorInfo constructorInfo;
|
||||
|
||||
#if NET_2_0
|
||||
#region Generated Function Cache
|
||||
|
||||
private static readonly IDictionary constructorCache = new Hashtable();
|
||||
|
||||
/// <summary>
|
||||
/// Obtains cached constructor info or creates a new entry, if none is found.
|
||||
/// </summary>
|
||||
private static ConstructorDelegate GetOrCreateDynamicConstructor(ConstructorInfo constructorInfo)
|
||||
{
|
||||
ConstructorDelegate method = (ConstructorDelegate)constructorCache[constructorInfo];
|
||||
if (method == null)
|
||||
{
|
||||
method = DynamicReflectionManager.CreateConstructor(constructorInfo);
|
||||
lock (constructorCache)
|
||||
{
|
||||
constructorCache[constructorInfo] = method;
|
||||
}
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private ConstructorDelegate constructor;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the safe constructor wrapper.
|
||||
/// </summary>
|
||||
/// <param name="constructorInfo">Constructor to wrap.</param>
|
||||
public SafeConstructor(ConstructorInfo constructorInfo)
|
||||
{
|
||||
this.constructorInfo = constructorInfo;
|
||||
this.constructor = GetOrCreateDynamicConstructor(constructorInfo);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Invokes dynamic constructor.
|
||||
/// </summary>
|
||||
/// <param name="arguments">
|
||||
/// Constructor arguments.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A constructor value.
|
||||
/// </returns>
|
||||
public object Invoke(object[] arguments)
|
||||
{
|
||||
return constructor(arguments);
|
||||
}
|
||||
#else
|
||||
private IDynamicConstructor dynamicConstructor;
|
||||
private bool isOptimized = false;
|
||||
|
||||
@@ -72,7 +125,7 @@ namespace Spring.Reflection.Dynamic
|
||||
/// <param name="constructor">Constructor to wrap.</param>
|
||||
public SafeConstructor(ConstructorInfo constructor)
|
||||
{
|
||||
this.constructor = constructor;
|
||||
this.constructorInfo = constructor;
|
||||
if (constructor.IsPublic &&
|
||||
ReflectionUtils.IsTypeVisible(constructor.DeclaringType, DynamicReflectionManager.ASSEMBLY_NAME))
|
||||
{
|
||||
@@ -80,7 +133,7 @@ namespace Spring.Reflection.Dynamic
|
||||
this.isOptimized = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Invokes dynamic constructor.
|
||||
/// </summary>
|
||||
@@ -103,18 +156,40 @@ namespace Spring.Reflection.Dynamic
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
isOptimized = false;
|
||||
return constructor.Invoke(arguments);
|
||||
return constructorInfo.Invoke(arguments);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return constructor.Invoke(arguments);
|
||||
return constructorInfo.Invoke(arguments);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#if NET_2_0
|
||||
/// <summary>
|
||||
/// Factory class for dynamic constructors.
|
||||
/// </summary>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
public class DynamicConstructor : BaseDynamicMember
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates dynamic constructor instance for the specified <see cref="ConstructorInfo"/>.
|
||||
/// </summary>
|
||||
/// <param name="constructorInfo">Constructor info to create dynamic constructor for.</param>
|
||||
/// <returns>Dynamic constructor for the specified <see cref="ConstructorInfo"/>.</returns>
|
||||
public static IDynamicConstructor Create(ConstructorInfo constructorInfo)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(constructorInfo, "You cannot create a dynamic constructor for a null value.");
|
||||
|
||||
return new SafeConstructor(constructorInfo);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
/// <summary>
|
||||
/// Factory class for dynamic constructors.
|
||||
/// </summary>
|
||||
@@ -162,37 +237,9 @@ namespace Spring.Reflection.Dynamic
|
||||
|
||||
ILGenerator il = invokeMethod.GetILGenerator();
|
||||
|
||||
Type[] argTypes = ReflectionUtils.GetParameterTypes(constructor);
|
||||
for (int i = 0; i < argTypes.Length; i++)
|
||||
{
|
||||
SetupConstructorArgument(il, argTypes[i], i);
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Newobj, constructor);
|
||||
ProcessReturnValue(il, constructor.DeclaringType);
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
private static void SetupConstructorArgument(ILGenerator il, Type argumentType, int argumentPosition)
|
||||
{
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.Emit(OpCodes.Ldc_I4, argumentPosition);
|
||||
il.Emit(OpCodes.Ldelem_Ref);
|
||||
if (argumentType.IsValueType)
|
||||
{
|
||||
#if NET_2_0
|
||||
il.Emit(OpCodes.Unbox_Any, argumentType);
|
||||
#else
|
||||
il.Emit(OpCodes.Unbox, argumentType);
|
||||
il.Emit(OpCodes.Ldobj, argumentType);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(OpCodes.Castclass, argumentType);
|
||||
}
|
||||
}
|
||||
|
||||
DynamicReflectionManager.EmitInvokeConstructor(il, constructor, true);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -85,10 +85,10 @@ namespace Spring.Reflection.Dynamic
|
||||
/// </summary>
|
||||
private class DynamicFieldCacheEntry
|
||||
{
|
||||
public readonly GetterDelegate Getter;
|
||||
public readonly SetterDelegate Setter;
|
||||
public readonly FieldGetterDelegate Getter;
|
||||
public readonly FieldSetterDelegate Setter;
|
||||
|
||||
public DynamicFieldCacheEntry(GetterDelegate getter, SetterDelegate setter)
|
||||
public DynamicFieldCacheEntry(FieldGetterDelegate getter, FieldSetterDelegate setter)
|
||||
{
|
||||
Getter = getter;
|
||||
Setter = setter;
|
||||
@@ -114,8 +114,8 @@ namespace Spring.Reflection.Dynamic
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly GetterDelegate getter;
|
||||
private readonly SetterDelegate setter;
|
||||
private readonly FieldGetterDelegate getter;
|
||||
private readonly FieldSetterDelegate setter;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the safe field wrapper.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#region License
|
||||
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2007 the original author or authors.
|
||||
*
|
||||
@@ -14,128 +14,280 @@
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using Spring.Reflection.Dynamic;
|
||||
using Spring.Util;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Reflection.Dynamic
|
||||
{
|
||||
#region IDynamicIndexer interface
|
||||
|
||||
/// <summary>
|
||||
/// Defines methods that dynamic indexer class has to implement.
|
||||
/// </summary>
|
||||
public interface IDynamicIndexer
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to get the indexer value from.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer argument.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A indexer value.
|
||||
/// </returns>
|
||||
object GetValue( object target, int index );
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to get the indexer value from.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer argument.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A indexer value.
|
||||
/// </returns>
|
||||
object GetValue( object target, object index );
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to get the indexer value from.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer arguments.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A indexer value.
|
||||
/// </returns>
|
||||
object GetValue( object target, object[] index );
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to set the indexer value on.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer argument.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A new indexer value.
|
||||
/// </param>
|
||||
void SetValue( object target, int index, object value );
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to set the indexer value on.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer argument.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A new indexer value.
|
||||
/// </param>
|
||||
void SetValue( object target, object index, object value );
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to set the indexer value on.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer arguments.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A new indexer value.
|
||||
/// </param>
|
||||
void SetValue( object target, object[] index, object value );
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Safe wrapper
|
||||
|
||||
#if NET_2_0
|
||||
/// <summary>
|
||||
/// Safe wrapper for the dynamic indexer.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="SafeIndexer"/> will attempt to use dynamic
|
||||
/// indexer if possible, but it will fall back to standard
|
||||
/// reflection if necessary.
|
||||
/// </remarks>
|
||||
[Obsolete("Use SafeProperty instead", false)]
|
||||
public class SafeIndexer : IDynamicIndexer
|
||||
{
|
||||
private PropertyInfo indexerProperty;
|
||||
|
||||
/// <summary>
|
||||
/// Internal PropertyInfo accessor.
|
||||
/// </summary>
|
||||
internal PropertyInfo IndexerProperty
|
||||
{
|
||||
get { return indexerProperty; }
|
||||
}
|
||||
|
||||
private SafeProperty property;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the safe indexer wrapper.
|
||||
/// </summary>
|
||||
/// <param name="indexerInfo">Indexer to wrap.</param>
|
||||
public SafeIndexer( PropertyInfo indexerInfo )
|
||||
{
|
||||
AssertUtils.ArgumentNotNull( indexerInfo, "You cannot create a dynamic indexer for a null value." );
|
||||
|
||||
this.indexerProperty = indexerInfo;
|
||||
this.property = new SafeProperty( indexerInfo );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to get indexer value from.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer arguments.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A indexer value.
|
||||
/// </returns>
|
||||
public object GetValue( object target, int index )
|
||||
{
|
||||
return property.GetValue( target, index );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to get the indexer value from.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer argument.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A indexer value.
|
||||
/// </returns>
|
||||
public object GetValue( object target, object index )
|
||||
{
|
||||
return property.GetValue( target, index );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to get indexer value from.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer arguments.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A indexer value.
|
||||
/// </returns>
|
||||
public object GetValue( object target, object[] index )
|
||||
{
|
||||
return property.GetValue( target, index );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to set indexer value on.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer arguments.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A new indexer value.
|
||||
/// </param>
|
||||
public void SetValue( object target, int index, object value )
|
||||
{
|
||||
property.SetValue( target, value, index );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to set indexer value on.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer arguments.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A new indexer value.
|
||||
/// </param>
|
||||
public void SetValue( object target, object index, object value )
|
||||
{
|
||||
property.SetValue( target, value, index );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to set indexer value on.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer arguments.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A new indexer value.
|
||||
/// </param>
|
||||
public void SetValue( object target, object[] index, object value )
|
||||
{
|
||||
property.SetValue( target, value, index );
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// Safe wrapper for the dynamic indexer.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="SafeIndexer"/> will attempt to use dynamic
|
||||
/// indexer if possible, but it will fall back to standard
|
||||
/// reflection if necessary.
|
||||
/// </remarks>
|
||||
public class SafeIndexer : IDynamicIndexer
|
||||
{
|
||||
private PropertyInfo indexerProperty;
|
||||
|
||||
/// <summary>
|
||||
/// Internal PropertyInfo accessor.
|
||||
/// </summary>
|
||||
internal PropertyInfo IndexerProperty
|
||||
{
|
||||
get { return indexerProperty; }
|
||||
}
|
||||
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using Spring.Util;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Reflection.Dynamic
|
||||
{
|
||||
#region IDynamicIndexer interface
|
||||
|
||||
/// <summary>
|
||||
/// Defines methods that dynamic indexer class has to implement.
|
||||
/// </summary>
|
||||
public interface IDynamicIndexer
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to get the indexer value from.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer argument.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A indexer value.
|
||||
/// </returns>
|
||||
object GetValue(object target, int index);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to get the indexer value from.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer argument.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A indexer value.
|
||||
/// </returns>
|
||||
object GetValue(object target, object index);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to get the indexer value from.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer arguments.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A indexer value.
|
||||
/// </returns>
|
||||
object GetValue(object target, object[] index);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to set the indexer value on.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer argument.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A new indexer value.
|
||||
/// </param>
|
||||
void SetValue(object target, int index, object value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to set the indexer value on.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer argument.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A new indexer value.
|
||||
/// </param>
|
||||
void SetValue(object target, object index, object value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to set the indexer value on.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer arguments.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A new indexer value.
|
||||
/// </param>
|
||||
void SetValue(object target, object[] index, object value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Safe wrapper
|
||||
|
||||
/// <summary>
|
||||
/// Safe wrapper for the dynamic indexer.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="SafeIndexer"/> will attempt to use dynamic
|
||||
/// indexer if possible, but it will fall back to standard
|
||||
/// reflection if necessary.
|
||||
/// </remarks>
|
||||
public class SafeIndexer : IDynamicIndexer
|
||||
{
|
||||
private PropertyInfo indexerProperty;
|
||||
private IDynamicIndexer dynamicIndexer;
|
||||
private bool isOptimizedGet = false;
|
||||
private bool isOptimizedSet = false;
|
||||
@@ -334,18 +486,38 @@ namespace Spring.Reflection.Dynamic
|
||||
indexerProperty.SetValue(target, value, index);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal PropertyInfo accessor.
|
||||
/// </summary>
|
||||
internal PropertyInfo IndexerProperty
|
||||
{
|
||||
get { return indexerProperty; }
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
#if NET_2_0
|
||||
/// <summary>
|
||||
/// Factory class for dynamic indexers.
|
||||
/// </summary>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
[Obsolete( "Use DynamicProperty instead", false )]
|
||||
public sealed class DynamicIndexer : BaseDynamicMember
|
||||
{
|
||||
/// <summary>
|
||||
/// Prevent instantiation
|
||||
/// </summary>
|
||||
private DynamicIndexer() { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates dynamic indexer instance for the specified <see cref="PropertyInfo"/>.
|
||||
/// </summary>
|
||||
/// <param name="indexer">Indexer info to create dynamic indexer for.</param>
|
||||
/// <returns>Dynamic indexer for the specified <see cref="PropertyInfo"/>.</returns>
|
||||
public static IDynamicIndexer Create( PropertyInfo indexer )
|
||||
{
|
||||
AssertUtils.ArgumentNotNull( indexer, "You cannot create a dynamic indexer for a null value." );
|
||||
|
||||
IDynamicIndexer dynamicIndexer = new SafeIndexer( indexer );
|
||||
return dynamicIndexer;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/// <summary>
|
||||
/// Factory class for dynamic indexers.
|
||||
/// </summary>
|
||||
@@ -354,7 +526,7 @@ namespace Spring.Reflection.Dynamic
|
||||
{
|
||||
private static readonly CreateIndexerCallback s_createCallback = new CreateIndexerCallback(CreateInternal);
|
||||
|
||||
#region Create Method
|
||||
#region Create Method
|
||||
|
||||
/// <summary>
|
||||
/// Creates dynamic indexer instance for the specified <see cref="PropertyInfo"/>.
|
||||
@@ -500,12 +672,8 @@ namespace Spring.Reflection.Dynamic
|
||||
}
|
||||
if (argumentType.IsValueType)
|
||||
{
|
||||
#if NET_2_0
|
||||
il.Emit(OpCodes.Unbox_Any, argumentType);
|
||||
#else
|
||||
il.Emit(OpCodes.Unbox, argumentType);
|
||||
il.Emit(OpCodes.Ldobj, argumentType);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -513,6 +681,8 @@ namespace Spring.Reflection.Dynamic
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
@@ -49,7 +49,7 @@ namespace Spring.Reflection.Dynamic
|
||||
/// <returns>
|
||||
/// A method return value.
|
||||
/// </returns>
|
||||
object Invoke(object target, object[] arguments);
|
||||
object Invoke(object target, params object[] arguments);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -66,7 +66,71 @@ namespace Spring.Reflection.Dynamic
|
||||
/// </remarks>
|
||||
public class SafeMethod : IDynamicMethod
|
||||
{
|
||||
private MethodInfo method;
|
||||
private readonly MethodInfo methodInfo;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the class, that declares this method
|
||||
/// </summary>
|
||||
public Type DeclaringType
|
||||
{
|
||||
get { return methodInfo.DeclaringType; }
|
||||
}
|
||||
|
||||
#if NET_2_0
|
||||
#region Generated Function Cache
|
||||
|
||||
private static readonly IDictionary methodCache = new Hashtable();
|
||||
|
||||
/// <summary>
|
||||
/// Obtains cached property info or creates a new entry, if none is found.
|
||||
/// </summary>
|
||||
private static FunctionDelegate GetOrCreateDynamicMethod(MethodInfo methodInfo)
|
||||
{
|
||||
FunctionDelegate method = (FunctionDelegate)methodCache[methodInfo];
|
||||
if (method == null)
|
||||
{
|
||||
method = DynamicReflectionManager.CreateMethod(methodInfo);
|
||||
lock (methodCache)
|
||||
{
|
||||
methodCache[methodInfo] = method;
|
||||
}
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly FunctionDelegate method;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the safe method wrapper.
|
||||
/// </summary>
|
||||
/// <param name="methodInfo">Method to wrap.</param>
|
||||
public SafeMethod(MethodInfo methodInfo)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(methodInfo, "You cannot create a dynamic method for a null value.");
|
||||
|
||||
this.methodInfo = methodInfo;
|
||||
this.method = GetOrCreateDynamicMethod(methodInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes dynamic method.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to invoke method on.
|
||||
/// </param>
|
||||
/// <param name="arguments">
|
||||
/// Method arguments.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A method return value.
|
||||
/// </returns>
|
||||
public object Invoke(object target, object[] arguments)
|
||||
{
|
||||
return this.method(target, arguments);
|
||||
}
|
||||
#else
|
||||
private IDynamicMethod dynamicMethod;
|
||||
private bool isOptimized = false;
|
||||
|
||||
@@ -76,7 +140,7 @@ namespace Spring.Reflection.Dynamic
|
||||
/// <param name="method">Method to wrap.</param>
|
||||
public SafeMethod(MethodInfo method)
|
||||
{
|
||||
this.method = method;
|
||||
this.methodInfo = method;
|
||||
if (method.IsPublic &&
|
||||
ReflectionUtils.IsTypeVisible(method.DeclaringType, DynamicReflectionManager.ASSEMBLY_NAME))
|
||||
{
|
||||
@@ -85,14 +149,6 @@ namespace Spring.Reflection.Dynamic
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the class, that declares this method
|
||||
/// </summary>
|
||||
public Type DeclaringType
|
||||
{
|
||||
get { return method.DeclaringType; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes dynamic method.
|
||||
/// </summary>
|
||||
@@ -123,12 +179,12 @@ namespace Spring.Reflection.Dynamic
|
||||
throw;
|
||||
}
|
||||
isOptimized = false;
|
||||
return method.Invoke(target, arguments);
|
||||
return methodInfo.Invoke(target, arguments);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return method.Invoke(target, arguments);
|
||||
return methodInfo.Invoke(target, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,10 +192,32 @@ namespace Spring.Reflection.Dynamic
|
||||
{
|
||||
return e.TargetSite.DeclaringType.FullName.IndexOf(DynamicReflectionManager.ASSEMBLY_NAME) >= 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#if NET_2_0
|
||||
/// <summary>
|
||||
/// Factory class for dynamic methods.
|
||||
/// </summary>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
public class DynamicMethod : BaseDynamicMember
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates dynamic method instance for the specified <see cref="MethodInfo"/>.
|
||||
/// </summary>
|
||||
/// <param name="method">Method info to create dynamic method for.</param>
|
||||
/// <returns>Dynamic method for the specified <see cref="MethodInfo"/>.</returns>
|
||||
public static IDynamicMethod Create(MethodInfo method)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(method, "You cannot create a dynamic method for a null value.");
|
||||
|
||||
IDynamicMethod dynamicMethod = new SafeMethod(method);
|
||||
return dynamicMethod;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/// <summary>
|
||||
/// Factory class for dynamic methods.
|
||||
/// </summary>
|
||||
@@ -187,104 +265,11 @@ namespace Spring.Reflection.Dynamic
|
||||
invokeMethod.DefineParameter(2, ParameterAttributes.None, "args");
|
||||
|
||||
ILGenerator il = invokeMethod.GetILGenerator();
|
||||
bool isValueType = method.DeclaringType.IsValueType;
|
||||
bool isStatic = method.IsStatic;
|
||||
|
||||
IDictionary outArgs = new Hashtable();
|
||||
ParameterInfo[] args = method.GetParameters();
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
if (IsOutputOrRefArgument(args[i]))
|
||||
{
|
||||
SetupOutputArgument(il, args[i], outArgs);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isStatic)
|
||||
{
|
||||
SetupTargetInstance(il, method.DeclaringType);
|
||||
}
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
SetupMethodArgument(il, args[i], outArgs);
|
||||
}
|
||||
InvokeMethod(il, isStatic, isValueType, method);
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
if (IsOutputOrRefArgument(args[i]))
|
||||
{
|
||||
ProcessOutputArgument(il, args[i], outArgs);
|
||||
}
|
||||
}
|
||||
ProcessReturnValue(il, method.ReturnType);
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
private static bool IsOutputOrRefArgument(ParameterInfo argInfo)
|
||||
{
|
||||
return argInfo.IsOut || argInfo.ParameterType.Name.EndsWith("&");
|
||||
}
|
||||
|
||||
private static void SetupOutputArgument(ILGenerator il, ParameterInfo argInfo, IDictionary outArgs)
|
||||
{
|
||||
Type argType = argInfo.ParameterType.GetElementType();
|
||||
|
||||
LocalBuilder lb = il.DeclareLocal(argType);
|
||||
if (!argInfo.IsOut)
|
||||
{
|
||||
PushArgumentValue(il, argType, argInfo.Position);
|
||||
il.Emit(OpCodes.Stloc, lb);
|
||||
}
|
||||
outArgs[argInfo.Position] = lb;
|
||||
}
|
||||
|
||||
private static void ProcessOutputArgument(ILGenerator il, ParameterInfo argInfo, IDictionary outArgs)
|
||||
{
|
||||
Type argType = argInfo.ParameterType.GetElementType();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_2);
|
||||
il.Emit(OpCodes.Ldc_I4, argInfo.Position);
|
||||
il.Emit(OpCodes.Ldloc, (LocalBuilder)outArgs[argInfo.Position]);
|
||||
if (argType.IsValueType)
|
||||
{
|
||||
il.Emit(OpCodes.Box, argType);
|
||||
}
|
||||
il.Emit(OpCodes.Stelem_Ref);
|
||||
}
|
||||
|
||||
private static void SetupMethodArgument(ILGenerator il, ParameterInfo argInfo, IDictionary outArgs)
|
||||
{
|
||||
if (IsOutputOrRefArgument(argInfo))
|
||||
{
|
||||
il.Emit(OpCodes.Ldloca_S, (LocalBuilder)outArgs[argInfo.Position]);
|
||||
}
|
||||
else
|
||||
{
|
||||
PushArgumentValue(il, argInfo.ParameterType, argInfo.Position);
|
||||
}
|
||||
}
|
||||
|
||||
private static void PushArgumentValue(ILGenerator il, Type argumentType, int argumentPosition)
|
||||
{
|
||||
il.Emit(OpCodes.Ldarg_2);
|
||||
il.Emit(OpCodes.Ldc_I4, argumentPosition);
|
||||
il.Emit(OpCodes.Ldelem_Ref);
|
||||
if (argumentType.IsValueType)
|
||||
{
|
||||
#if NET_2_0
|
||||
il.Emit(OpCodes.Unbox_Any, argumentType);
|
||||
#else
|
||||
il.Emit(OpCodes.Unbox, argumentType);
|
||||
il.Emit(OpCodes.Ldobj, argumentType);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(OpCodes.Castclass, argumentType);
|
||||
}
|
||||
DynamicReflectionManager.EmitInvokeMethod(il, method, true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -60,6 +60,30 @@ namespace Spring.Reflection.Dynamic
|
||||
/// A new property value.
|
||||
/// </param>
|
||||
void SetValue(object target, object value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic property for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to get property value from.
|
||||
/// </param>
|
||||
/// <param name="index">Optional index values for indexed properties. This value should be null reference for non-indexed properties.</param>
|
||||
/// <returns>
|
||||
/// A property value.
|
||||
/// </returns>
|
||||
object GetValue(object target, params object[] index);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic property for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to set property value on.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A new property value.
|
||||
/// </param>
|
||||
/// <param name="index">Optional index values for indexed properties. This value should be null reference for non-indexed properties.</param>
|
||||
void SetValue(object target, object value, params object[] index);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -91,10 +115,10 @@ namespace Spring.Reflection.Dynamic
|
||||
/// </summary>
|
||||
private class DynamicPropertyCacheEntry
|
||||
{
|
||||
public readonly GetterDelegate Getter;
|
||||
public readonly SetterDelegate Setter;
|
||||
public readonly PropertyGetterDelegate Getter;
|
||||
public readonly PropertySetterDelegate Setter;
|
||||
|
||||
public DynamicPropertyCacheEntry(GetterDelegate getter, SetterDelegate setter)
|
||||
public DynamicPropertyCacheEntry(PropertyGetterDelegate getter, PropertySetterDelegate setter)
|
||||
{
|
||||
Getter = getter;
|
||||
Setter = setter;
|
||||
@@ -120,8 +144,8 @@ namespace Spring.Reflection.Dynamic
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly GetterDelegate getter;
|
||||
private readonly SetterDelegate setter;
|
||||
private readonly PropertyGetterDelegate getter;
|
||||
private readonly PropertySetterDelegate setter;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the safe property wrapper.
|
||||
@@ -151,6 +175,21 @@ namespace Spring.Reflection.Dynamic
|
||||
return getter(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic property for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to get property value from.
|
||||
/// </param>
|
||||
/// <param name="index">Optional index values for indexed properties. This value should be null reference for non-indexed properties.</param>
|
||||
/// <returns>
|
||||
/// A property value.
|
||||
/// </returns>
|
||||
public object GetValue(object target, params object[] index)
|
||||
{
|
||||
return getter(target, index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic property for the specified target object.
|
||||
/// </summary>
|
||||
@@ -165,6 +204,21 @@ namespace Spring.Reflection.Dynamic
|
||||
setter(target, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic property for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to set property value on.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A new property value.
|
||||
/// </param>
|
||||
/// <param name="index">Optional index values for indexed properties. This value should be null reference for non-indexed properties.</param>
|
||||
public void SetValue(object target, object value, params object[] index)
|
||||
{
|
||||
setter(target, value, index);
|
||||
}
|
||||
|
||||
#else
|
||||
private readonly IDynamicProperty dynamicProperty;
|
||||
private readonly bool isOptimizedGet = false;
|
||||
@@ -239,8 +293,9 @@ namespace Spring.Reflection.Dynamic
|
||||
{
|
||||
dynamicProperty.SetValue(target, value);
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
catch (InvalidCastException ex)
|
||||
{
|
||||
Log.Debug("Failed optimized set", ex);
|
||||
isOptimizedSet = false;
|
||||
propertyInfo.SetValue(target, value, null);
|
||||
}
|
||||
@@ -268,6 +323,64 @@ namespace Spring.Reflection.Dynamic
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to get indexer value from.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer arguments.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A indexer value.
|
||||
/// </returns>
|
||||
public object GetValue(object target, object[] index)
|
||||
{
|
||||
if (isOptimizedGet)
|
||||
{
|
||||
try
|
||||
{
|
||||
return dynamicProperty.GetValue(target, index);
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
isOptimizedSet = false;
|
||||
}
|
||||
}
|
||||
return propertyInfo.GetValue(target, index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of the dynamic indexer for the specified target object.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// Target object to set indexer value on.
|
||||
/// </param>
|
||||
/// <param name="index">
|
||||
/// Indexer arguments.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A new indexer value.
|
||||
/// </param>
|
||||
public void SetValue(object target, object value, object[] index)
|
||||
{
|
||||
if (isOptimizedSet)
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamicProperty.SetValue(target, value, index);
|
||||
return;
|
||||
}
|
||||
catch (InvalidCastException ex)
|
||||
{
|
||||
Log.Debug("Failed optimized set", ex);
|
||||
isOptimizedSet = false;
|
||||
}
|
||||
}
|
||||
propertyInfo.SetValue(target, value, index);
|
||||
}
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Internal PropertyInfo accessor.
|
||||
@@ -364,7 +477,9 @@ namespace Spring.Reflection.Dynamic
|
||||
tb.AddInterfaceImplementation(typeof(IDynamicProperty));
|
||||
|
||||
GenerateGetValue(tb, property);
|
||||
GenerateGetIndexedValue(tb, property);
|
||||
GenerateSetValue(tb, property);
|
||||
GenerateSetIndexedValue(tb, property);
|
||||
|
||||
Type dynamicPropertyType = tb.CreateType();
|
||||
ConstructorInfo ctor = dynamicPropertyType.GetConstructor(Type.EmptyTypes);
|
||||
@@ -401,6 +516,41 @@ namespace Spring.Reflection.Dynamic
|
||||
}
|
||||
}
|
||||
|
||||
private static void GenerateGetIndexedValue(TypeBuilder tb, PropertyInfo indexer)
|
||||
{
|
||||
MethodBuilder getValueMethod =
|
||||
tb.DefineMethod("GetValue", METHOD_ATTRIBUTES, typeof(object), new Type[] { typeof(object), typeof(object[]) });
|
||||
getValueMethod.DefineParameter(1, ParameterAttributes.None, "target");
|
||||
getValueMethod.DefineParameter(2, ParameterAttributes.None, "index");
|
||||
|
||||
ILGenerator il = getValueMethod.GetILGenerator();
|
||||
if (indexer.CanRead)
|
||||
{
|
||||
MethodInfo getMethod = indexer.GetGetMethod();
|
||||
bool isValueType = indexer.DeclaringType.IsValueType;
|
||||
bool isStatic = getMethod.IsStatic;
|
||||
|
||||
if (!isStatic)
|
||||
{
|
||||
SetupTargetInstance(il, indexer.DeclaringType);
|
||||
}
|
||||
|
||||
Type[] argTypes = ReflectionUtils.GetParameterTypes(getMethod);
|
||||
for (int i = 0; i < argTypes.Length; i++)
|
||||
{
|
||||
SetupIndexerArgument(il, 2, argTypes[i], i, true);
|
||||
}
|
||||
|
||||
InvokeMethod(il, isStatic, isValueType, getMethod);
|
||||
ProcessReturnValue(il, indexer.PropertyType);
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowInvalidOperationException(il, "Cannot get value of a non-readable indexer");
|
||||
}
|
||||
}
|
||||
|
||||
private static void GenerateSetValue(TypeBuilder tb, PropertyInfo property)
|
||||
{
|
||||
MethodBuilder setValueMethod =
|
||||
@@ -440,6 +590,71 @@ namespace Spring.Reflection.Dynamic
|
||||
}
|
||||
}
|
||||
|
||||
private static void GenerateSetIndexedValue(TypeBuilder tb, PropertyInfo indexer)
|
||||
{
|
||||
MethodBuilder setValueMethod =
|
||||
tb.DefineMethod("SetValue", METHOD_ATTRIBUTES, typeof(void),
|
||||
new Type[] { typeof(object), typeof(object), typeof(object[]) });
|
||||
setValueMethod.DefineParameter(1, ParameterAttributes.None, "target");
|
||||
setValueMethod.DefineParameter(2, ParameterAttributes.None, "value");
|
||||
setValueMethod.DefineParameter(3, ParameterAttributes.None, "index");
|
||||
|
||||
ILGenerator il = setValueMethod.GetILGenerator();
|
||||
if (indexer.CanWrite)
|
||||
{
|
||||
bool isValueType = indexer.DeclaringType.IsValueType;
|
||||
if (isValueType)
|
||||
{
|
||||
ThrowInvalidOperationException(il, "Cannot set indexer value on a value type due to boxing.");
|
||||
}
|
||||
else
|
||||
{
|
||||
MethodInfo setMethod = indexer.GetSetMethod();
|
||||
bool isStatic = setMethod.IsStatic;
|
||||
|
||||
if (!isStatic)
|
||||
{
|
||||
SetupTargetInstance(il, indexer.DeclaringType);
|
||||
}
|
||||
|
||||
Type[] argTypes = ReflectionUtils.GetParameterTypes(setMethod);
|
||||
for (int i = 0; i < argTypes.Length - 1; i++)
|
||||
{
|
||||
SetupIndexerArgument(il, 3, argTypes[i], i, true);
|
||||
}
|
||||
|
||||
SetupArgument(il, indexer.PropertyType, 2);
|
||||
InvokeMethod(il, isStatic, isValueType, setMethod);
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowInvalidOperationException(il, "Cannot set value of a read-only indexer");
|
||||
}
|
||||
}
|
||||
|
||||
private static OpCode[] LdArgOpCodes = { OpCodes.Ldarg_0, OpCodes.Ldarg_1, OpCodes.Ldarg_2, OpCodes.Ldarg_3 };
|
||||
|
||||
private static void SetupIndexerArgument(ILGenerator il, int indexArgumentPosition, Type argumentType, int argumentPosition, bool isObjectArray)
|
||||
{
|
||||
il.Emit(LdArgOpCodes[indexArgumentPosition]);
|
||||
if (isObjectArray)
|
||||
{
|
||||
il.Emit(OpCodes.Ldc_I4, argumentPosition);
|
||||
il.Emit(OpCodes.Ldelem_Ref);
|
||||
}
|
||||
if (argumentType.IsValueType)
|
||||
{
|
||||
il.Emit(OpCodes.Unbox, argumentType);
|
||||
il.Emit(OpCodes.Ldobj, argumentType);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(OpCodes.Castclass, argumentType);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -260,16 +260,6 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Util\ControlAccessor.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Util\ControlCollectionAccessor.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Util\HttpContextSwitch.cs"
|
||||
SubType = "Code"
|
||||
@@ -380,6 +370,16 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\Support\ControlAccessor.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\Support\ControlCollectionAccessor.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\Support\ControlInterceptor.cs"
|
||||
SubType = "Code"
|
||||
@@ -460,6 +460,11 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\Support\LocalResourceManager.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\Support\MappingHandlerFactory.cs"
|
||||
SubType = "Code"
|
||||
@@ -545,6 +550,11 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\UI\IModelPersistenceMedium.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\UI\IValidationContainer.cs"
|
||||
SubType = "Code"
|
||||
@@ -560,6 +570,11 @@
|
||||
SubType = "ASPXCodeBehind"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\UI\SessionModelPersistenceMedium.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\UI\UserControl.cs"
|
||||
SubType = "ASPXCodeBehind"
|
||||
|
||||
@@ -29,6 +29,8 @@ using Spring.Util;
|
||||
|
||||
#endregion
|
||||
|
||||
#if NET_2_0
|
||||
|
||||
namespace Spring.Web.Support
|
||||
{
|
||||
/// <summary>
|
||||
@@ -88,4 +90,6 @@ namespace Spring.Web.Support
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -21,10 +21,13 @@
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Spring.Objects;
|
||||
|
||||
#if NET_2_0
|
||||
using System.Collections.Generic;
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Core.TypeResolution
|
||||
@@ -39,10 +42,6 @@ namespace Spring.Core.TypeResolution
|
||||
[Test]
|
||||
public void CanTakeQualifiedType()
|
||||
{
|
||||
string tn = typeof(int[]).AssemblyQualifiedName;
|
||||
tn = typeof(TestGenericObject<int,string>[]).AssemblyQualifiedName;
|
||||
tn = typeof(List<int>).AssemblyQualifiedName;
|
||||
|
||||
Type testType = typeof(TestObject);
|
||||
TypeAssemblyHolder tah = new TypeAssemblyHolder(testType.AssemblyQualifiedName);
|
||||
Assert.IsTrue(tah.IsAssemblyQualified);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Spring.Context.Support;
|
||||
|
||||
@@ -74,6 +77,44 @@ namespace Spring.Reflection.Dynamic
|
||||
Assert.AreEqual(mostImportantDayInTheWorldEver.Year, year.GetValue(mostImportantDayInTheWorldEver));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AccessInheritedPropertyFromBaseClass()
|
||||
{
|
||||
IDynamicProperty p = Create(typeof(ClassWithNonReadableProperty).GetProperty("MyBaseProperty"));
|
||||
BaseClass baseObject = new BaseClass();
|
||||
baseObject.MyBaseProperty = "testtext";
|
||||
Assert.AreEqual("testtext", p.GetValue(baseObject));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AccessInheritedPropertyFromDerivedClass()
|
||||
{
|
||||
IDynamicProperty p = Create(typeof(BaseClass).GetProperty("MyBaseProperty"));
|
||||
ClassWithNonReadableProperty derivedObject = new ClassWithNonReadableProperty();
|
||||
derivedObject.MyBaseProperty = "testtext";
|
||||
Assert.AreEqual("testtext", p.GetValue(derivedObject));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AccessOverriddenProperty()
|
||||
{
|
||||
IDynamicProperty pVirt = Create(typeof(BaseClass).GetProperty("MyVirtualBaseProperty"));
|
||||
IDynamicProperty pOverridden = Create(typeof(ClassWithNonReadableProperty).GetProperty("MyVirtualBaseProperty"));
|
||||
|
||||
Assert.AreEqual("MyVirtualBasePropertyText", pVirt.GetValue(new BaseClass()));
|
||||
try
|
||||
{
|
||||
Assert.AreEqual("MyVirtualBasePropertyText", pOverridden.GetValue(new BaseClass()));
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
}
|
||||
Assert.AreEqual("MyOverridenDerivedPropertyText", pVirt.GetValue(new ClassWithNonReadableProperty()));
|
||||
Assert.AreEqual("MyOverridenDerivedPropertyText", pOverridden.GetValue(new ClassWithNonReadableProperty()));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void TestStaticProperties()
|
||||
{
|
||||
@@ -178,7 +219,7 @@ namespace Spring.Reflection.Dynamic
|
||||
|
||||
#region IL generation helper classes (they help if you look at them in Reflector ;-)
|
||||
|
||||
public class ValueTypeProperty : IDynamicProperty
|
||||
public class ValueTypeProperty //: IDynamicProperty
|
||||
{
|
||||
public object GetValue(object target)
|
||||
{
|
||||
@@ -191,7 +232,7 @@ namespace Spring.Reflection.Dynamic
|
||||
}
|
||||
}
|
||||
|
||||
public class ValueTypeTarget : IDynamicProperty
|
||||
public class ValueTypeTarget //: IDynamicProperty
|
||||
{
|
||||
public object GetValue(object target)
|
||||
{
|
||||
@@ -205,7 +246,7 @@ namespace Spring.Reflection.Dynamic
|
||||
}
|
||||
}
|
||||
|
||||
public class StaticProperty : IDynamicProperty
|
||||
public class StaticProperty //: IDynamicProperty
|
||||
{
|
||||
public object GetValue(object target)
|
||||
{
|
||||
@@ -256,7 +297,23 @@ namespace Spring.Reflection.Dynamic
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassWithNonReadableProperty
|
||||
public class BaseClass
|
||||
{
|
||||
private string myBaseProperty;
|
||||
|
||||
public string MyBaseProperty
|
||||
{
|
||||
set { myBaseProperty = value; }
|
||||
get { return myBaseProperty; }
|
||||
}
|
||||
|
||||
public virtual string MyVirtualBaseProperty
|
||||
{
|
||||
get { return "MyVirtualBasePropertyText"; }
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassWithNonReadableProperty : BaseClass
|
||||
{
|
||||
private string myProperty;
|
||||
|
||||
@@ -264,6 +321,11 @@ namespace Spring.Reflection.Dynamic
|
||||
{
|
||||
set { myProperty = value; }
|
||||
}
|
||||
|
||||
public override string MyVirtualBaseProperty
|
||||
{
|
||||
get { return "MyOverridenDerivedPropertyText"; }
|
||||
}
|
||||
}
|
||||
|
||||
#if NET_2_0
|
||||
|
||||
@@ -108,6 +108,38 @@ namespace Spring.Reflection.Dynamic
|
||||
Assert.IsFalse((bool) isNullOrEmpty.Invoke(null, new object[] { "Ana Maria" }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestArgumentTypeCasts()
|
||||
{
|
||||
IDynamicMethod sqrt = DynamicMethod.Create(typeof(Math).GetMethod("Sqrt"));
|
||||
object result = sqrt.Invoke(null, new object[] { 4 } );
|
||||
Assert.AreEqual( Math.Sqrt(4), result );
|
||||
|
||||
try
|
||||
{
|
||||
sqrt.Invoke(null, new object[] { null } );
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
sqrt.Invoke(null, new object[] { "4" } );
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{}
|
||||
}
|
||||
|
||||
private void CodeForReflection()
|
||||
{
|
||||
object val = 4;
|
||||
Type argType = typeof(double);
|
||||
Math.Sqrt( (double)Convert.ChangeType(val, argType) );
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRefOutMethods()
|
||||
{
|
||||
|
||||
@@ -21,8 +21,11 @@
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Spring.Context.Support;
|
||||
|
||||
@@ -30,52 +33,52 @@ using Spring.Context.Support;
|
||||
|
||||
namespace Spring.Reflection.Dynamic
|
||||
{
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Unit tests for the DynamicProperty class.
|
||||
/// </summary>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
[TestFixture]
|
||||
[TestFixture]
|
||||
public class DynamicPropertyTests : BasePropertyTests
|
||||
{
|
||||
protected override IDynamicProperty Create(PropertyInfo property)
|
||||
protected override IDynamicProperty Create( PropertyInfo property )
|
||||
{
|
||||
return DynamicProperty.Create(property);
|
||||
return DynamicProperty.Create( property );
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
[ExpectedException( typeof( InvalidOperationException ) )]
|
||||
public void TestNonReadableProperties()
|
||||
{
|
||||
IDynamicProperty nonReadableProperty =
|
||||
Create(typeof(ClassWithNonReadableProperty).GetProperty("MyProperty"));
|
||||
nonReadableProperty.GetValue(null);
|
||||
IDynamicProperty nonReadableProperty =
|
||||
Create( typeof( ClassWithNonReadableProperty ).GetProperty( "MyProperty" ) );
|
||||
nonReadableProperty.GetValue( null );
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
[ExpectedException( typeof( InvalidOperationException ) )]
|
||||
public void TestNonWritableInstanceProperty()
|
||||
{
|
||||
IDynamicProperty nonWritableProperty =
|
||||
Create(typeof(Inventor).GetProperty("PlaceOfBirth"));
|
||||
nonWritableProperty.SetValue(null, null);
|
||||
Create( typeof( Inventor ).GetProperty( "PlaceOfBirth" ) );
|
||||
nonWritableProperty.SetValue( null, null );
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
[ExpectedException( typeof( InvalidOperationException ) )]
|
||||
public void TestAttemptingToSetPropertyOfValueTypeInstance()
|
||||
{
|
||||
MyStruct myYearHolder = new MyStruct();
|
||||
IDynamicProperty year = Create(typeof(MyStruct).GetProperty("Year"));
|
||||
year.SetValue(myYearHolder, 2004);
|
||||
IDynamicProperty year = Create( typeof( MyStruct ).GetProperty( "Year" ) );
|
||||
year.SetValue( myYearHolder, 2004 );
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
[ExpectedException( typeof( InvalidOperationException ) )]
|
||||
public void TestNonWritableStaticProperty()
|
||||
{
|
||||
IDynamicProperty nonWritableProperty =
|
||||
Create(typeof(DateTime).GetProperty("Today"));
|
||||
nonWritableProperty.SetValue(null, null);
|
||||
}
|
||||
Create( typeof( DateTime ).GetProperty( "Today" ) );
|
||||
nonWritableProperty.SetValue( null, null );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,11 @@
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Microsoft.VisualBasic;
|
||||
using NUnit.Framework;
|
||||
|
||||
#endregion
|
||||
@@ -41,6 +45,53 @@ namespace Spring.Reflection.Dynamic
|
||||
return new SafeProperty(property);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void CanGetSetSimpleProperty()
|
||||
{
|
||||
object o = GetVisualBasicTestObject();
|
||||
IDynamicProperty simpleProperty = Create(o.GetType().GetProperty("SimpleProperty"));
|
||||
simpleProperty.SetValue(o, "CanGetSimpleText", "args");
|
||||
Assert.AreEqual("CanGetSimpleText", ThisLastPropertyValue.GetValue(o));
|
||||
Assert.AreEqual("CanGetSimpleText", simpleProperty.GetValue(o));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanGetSetSimpleIndexer()
|
||||
{
|
||||
object o = GetVisualBasicTestObject();
|
||||
IDynamicProperty simpleProperty = Create(o.GetType().GetProperty("SimpleIndexer"));
|
||||
|
||||
// write
|
||||
simpleProperty.SetValue(o, "CanGetSetSimpleIndexer", 2);
|
||||
Assert.AreEqual("CanGetSetSimpleIndexer", ThisLastPropertyValue.GetValue(o));
|
||||
Assert.AreEqual(2, ThisArg1.GetValue(o));
|
||||
|
||||
// read
|
||||
object value = simpleProperty.GetValue(o, 3);
|
||||
Assert.AreEqual("CanGetSetSimpleIndexer", value);
|
||||
Assert.AreEqual(3, ThisArg1.GetValue(o));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanGetSetComplexIndexer()
|
||||
{
|
||||
object o = GetVisualBasicTestObject();
|
||||
IDynamicProperty property = Create(o.GetType().GetProperty("ComplexIndexer"));
|
||||
|
||||
// write
|
||||
property.SetValue(o, "CanGetSetComplexIndexer", 2, "Arg2");
|
||||
Assert.AreEqual("CanGetSetComplexIndexer", ThisLastPropertyValue.GetValue(o));
|
||||
Assert.AreEqual(2.0, (double)ThisArg1.GetValue(o));
|
||||
Assert.AreEqual("Arg2", ThisArg2.GetValue(o));
|
||||
|
||||
// read
|
||||
object value = property.GetValue(o, 3, "Arg3");
|
||||
Assert.AreEqual("CanGetSetComplexIndexer", value);
|
||||
Assert.AreEqual(3.0, (double)ThisArg1.GetValue(o));
|
||||
Assert.AreEqual("Arg3", ThisArg2.GetValue(o));
|
||||
}
|
||||
|
||||
#if NET_2_0
|
||||
[Test]
|
||||
public void TestForRestrictiveSetterWithSafeWrapper()
|
||||
@@ -76,6 +127,60 @@ namespace Spring.Reflection.Dynamic
|
||||
Assert.AreEqual(123, first.GetValue(something));
|
||||
}
|
||||
#endif
|
||||
|
||||
#region VB TestClass Code
|
||||
|
||||
private static Type s__visualBasicTestObjectType;
|
||||
private static IDynamicField ThisLastPropertyValue;
|
||||
private static IDynamicField ThisArg1;
|
||||
private static IDynamicField ThisArg2;
|
||||
private static IDynamicField ThisOptionalArg;
|
||||
private static IDynamicField ThisParamsArg;
|
||||
|
||||
protected static object GetVisualBasicTestObject()
|
||||
{
|
||||
if (s__visualBasicTestObjectType == null)
|
||||
{
|
||||
// compile vb test class
|
||||
string vbSourceCode = new StreamReader( Assembly.GetExecutingAssembly().GetManifestResourceStream( typeof( BasePropertyTests ), "SafePropertyTests_TestObject.vb" ) ).ReadToEnd();
|
||||
|
||||
CompilerParameters args = new CompilerParameters();
|
||||
args.OutputAssembly = "VbTestObject.dll";
|
||||
args.GenerateInMemory = true;
|
||||
args.GenerateExecutable = false;
|
||||
args.IncludeDebugInformation = true;
|
||||
args.Evidence = Assembly.GetExecutingAssembly().Evidence;
|
||||
#if NET_2_0
|
||||
CodeDomProvider provider = CodeDomProvider.CreateProvider( "VisualBasic" );
|
||||
CompilerResults results = provider.CompileAssemblyFromSource( args, vbSourceCode );
|
||||
#else
|
||||
CodeDomProvider provider = new VBCodeProvider();
|
||||
ICodeCompiler compiler = provider.CreateCompiler();
|
||||
CompilerResults results = compiler.CompileAssemblyFromSource( args, vbSourceCode );
|
||||
#endif
|
||||
if (results.Errors.HasErrors)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (CompilerError error in results.Errors)
|
||||
{
|
||||
sb.Append( error.ToString() ).Append( "\n\r" );
|
||||
}
|
||||
throw new TypeLoadException( "failed compiling test class: " + sb );
|
||||
}
|
||||
s__visualBasicTestObjectType = results.CompiledAssembly.GetType( "VbTestObject" );
|
||||
ThisLastPropertyValue = DynamicField.Create( s__visualBasicTestObjectType.GetField("ThisLastPropertyValue") );
|
||||
ThisArg1 = DynamicField.Create( s__visualBasicTestObjectType.GetField("ThisArg1") );
|
||||
ThisArg2 = DynamicField.Create( s__visualBasicTestObjectType.GetField("ThisArg2") );
|
||||
ThisOptionalArg = DynamicField.Create( s__visualBasicTestObjectType.GetField("ThisOptionalArg") );
|
||||
ThisParamsArg = DynamicField.Create( s__visualBasicTestObjectType.GetField("ThisParamsArgs") );
|
||||
}
|
||||
|
||||
object s__visualBasicTestObject = Activator.CreateInstance(s__visualBasicTestObjectType);
|
||||
|
||||
return s__visualBasicTestObject;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region Test Classes
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
Public Class VbTestObject
|
||||
Public ThisArg1 As Object
|
||||
Public ThisArg2 As Object
|
||||
Public ThisOptionalArg As Object
|
||||
Public ThisParamsArgs As Object()
|
||||
Public ThisLastPropertyValue As Object
|
||||
|
||||
Property SimpleProperty() As String
|
||||
Get
|
||||
Return ThisLastPropertyValue
|
||||
End Get
|
||||
Set(ByVal value As String)
|
||||
ThisLastPropertyValue = value
|
||||
End Set
|
||||
End Property
|
||||
|
||||
Property SimpleIndexer(ByVal arg1 As Integer) As String
|
||||
Get
|
||||
ThisArg1 = arg1
|
||||
Return ThisLastPropertyValue
|
||||
End Get
|
||||
Set(ByVal value As String)
|
||||
ThisArg1 = arg1
|
||||
ThisLastPropertyValue = value
|
||||
End Set
|
||||
End Property
|
||||
|
||||
Default Property ComplexIndexer(ByVal arg1 As Double, ByVal arg2 As Object) As String
|
||||
Get
|
||||
ThisArg1 = arg1
|
||||
ThisArg2 = arg2
|
||||
Return ThisLastPropertyValue
|
||||
End Get
|
||||
Set(ByVal value As String)
|
||||
ThisArg1 = arg1
|
||||
ThisArg2 = arg2
|
||||
ThisLastPropertyValue = value
|
||||
End Set
|
||||
End Property
|
||||
|
||||
Property PropertyWithParamsArgs(ByVal arg1 As String, ByVal ParamArray paramsArgs As Object()) As String
|
||||
Get
|
||||
ThisArg1 = arg1
|
||||
ThisParamsArgs = paramsArgs
|
||||
Return ThisLastPropertyValue
|
||||
End Get
|
||||
Set(ByVal value As String)
|
||||
ThisArg1 = arg1
|
||||
ThisParamsArgs = paramsArgs
|
||||
ThisLastPropertyValue = value
|
||||
End Set
|
||||
End Property
|
||||
|
||||
|
||||
Property PropertyWithOptionalArg(ByVal arg1 As String, Optional ByVal optionalArg As Object = "Empty") As String
|
||||
Get
|
||||
ThisArg1 = arg1
|
||||
ThisOptionalArg = optionalArg
|
||||
Return ThisLastPropertyValue
|
||||
End Get
|
||||
Set(ByVal value As String)
|
||||
ThisArg1 = arg1
|
||||
ThisOptionalArg = optionalArg
|
||||
ThisLastPropertyValue = value
|
||||
End Set
|
||||
End Property
|
||||
|
||||
End Class
|
||||
@@ -1744,6 +1744,10 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Reflection\Dynamic\SafePropertyTests_TestObject.vb"
|
||||
BuildAction = "EmbeddedResource"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Resources\Images.resx"
|
||||
BuildAction = "EmbeddedResource"
|
||||
|
||||
@@ -640,6 +640,7 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Reflection\Dynamic\BasePropertyTests.cs" />
|
||||
<EmbeddedResource Include="Reflection\Dynamic\SafePropertyTests_TestObject.vb" />
|
||||
<Compile Include="Reflection\Dynamic\DynamicConstructorTests.cs" />
|
||||
<Compile Include="Reflection\Dynamic\DynamicFieldTests.cs" />
|
||||
<Compile Include="Reflection\Dynamic\DynamicIndexerTests.cs" />
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
<include name="**/*.resx" />
|
||||
<include name="**/*.xsd" />
|
||||
<include name="**/*.txt" />
|
||||
<include name="**/*.vb" />
|
||||
<include name="**/*.properties" />
|
||||
<include name="**/SimpleAppContext.xml" />
|
||||
<include name="**/Factory/Attributes/*.xml" />
|
||||
|
||||
@@ -151,6 +151,11 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\AdoTemplatePerformanceTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\AdoTemplateTests.cs"
|
||||
SubType = "Code"
|
||||
@@ -272,6 +277,11 @@
|
||||
RelPath = "Data\nativeAdoTests.xml"
|
||||
BuildAction = "EmbeddedResource"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\NestedTxScopeTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\OracleAdoTemplateTests.cs"
|
||||
SubType = "Code"
|
||||
@@ -296,6 +306,11 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\SQLiteTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\StoredProcedureTests.cs"
|
||||
SubType = "Code"
|
||||
@@ -334,11 +349,44 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\TestTxIsolationLevel.xml"
|
||||
BuildAction = "EmbeddedResource"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\TestTxIsolationLevelTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\TransactionTemplateTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\Generic\GenericAdoTemplateTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\Generic\GenericAdoTemplateTests.xml"
|
||||
BuildAction = "Content"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\Generic\ITestObjectDao.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\Generic\TestObjectDao.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\Generic\TestObjectRowMapper.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\Northwind\AdoTemplateShipperDao.cs"
|
||||
SubType = "Code"
|
||||
@@ -359,6 +407,26 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\Objects\Generic\MappingVacationQuery.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\Objects\Generic\StoredProcedureTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\Objects\Generic\Vacation.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\Objects\Generic\VacationRowMapper.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Data\Support\SimpleExceptionTranslationTests.cs"
|
||||
SubType = "Code"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<ProjectType>Local</ProjectType>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{91766D21-C568-459F-9BEA-759B011F23CF}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -127,6 +127,7 @@
|
||||
<Compile Include="Data\AutoDeclarativeTxTests.cs" />
|
||||
<Compile Include="Data\CallCreateTestObject.cs" />
|
||||
<Compile Include="Data\ConsoleLoggingAroundAdvice.cs" />
|
||||
<Compile Include="Data\OracleAdoTemplateTests.cs" />
|
||||
<Compile Include="Data\TestTxIsolationLevelTests.cs" />
|
||||
<Compile Include="Data\Generic\GenericAdoTemplateTests.cs" />
|
||||
<Compile Include="Data\Generic\ITestObjectDao.cs" />
|
||||
@@ -185,6 +186,12 @@
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Data\TestTxIsolationLevel.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Data\CreateTestObject.sql" />
|
||||
<Content Include="Data\CreditsDebitsSchema.sql" />
|
||||
<Content Include="Data\DTC1.1AppContext.xml" />
|
||||
<Content Include="Data\testobjects-sqlserver.sql" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
|
||||
@@ -244,6 +244,11 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TestSupport\DictionaryModelPersistenceMedium.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TestSupport\NUnitAdapter.cs"
|
||||
SubType = "Code"
|
||||
@@ -259,6 +264,11 @@
|
||||
SubType = "ASPXCodeBehind"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TestSupport\TestUserControl.cs"
|
||||
SubType = "ASPXCodeBehind"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TestSupport\TestWebContext.cs"
|
||||
SubType = "Code"
|
||||
@@ -289,15 +299,6 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Util\ControlInterceptionTests.cs"
|
||||
SubType = "ASPXCodeBehind"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Util\ControlInterceptionTests.objects.xml"
|
||||
BuildAction = "EmbeddedResource"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Util\WebDIPerformanceTests.cs"
|
||||
SubType = "Code"
|
||||
@@ -318,6 +319,20 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\Support\ControlInterceptionTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\Support\ControlInterceptionTests.objects.xml"
|
||||
BuildAction = "EmbeddedResource"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\Support\LocalResourceManagerTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\Support\MimeMediaTypeTests.cs"
|
||||
SubType = "Code"
|
||||
@@ -343,6 +358,11 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\UI\SessionModelPersistenceMediumTests.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web\UI\UserControlTests.cs"
|
||||
SubType = "Code"
|
||||
|
||||
@@ -30,7 +30,7 @@ using Spring.Web.Support;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Util
|
||||
namespace Spring.Web.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the ControlInterceptor class.
|
||||
@@ -40,7 +40,7 @@ namespace Spring.Util
|
||||
public class ControlInterceptionTests
|
||||
{
|
||||
private const string RES_OBJECTS =
|
||||
"assembly://Spring.Web.Tests/Spring.Util/ControlInterceptionTests.objects.xml";
|
||||
"assembly://Spring.Web.Tests/Spring.Web.Support/ControlInterceptionTests.objects.xml";
|
||||
|
||||
static ControlInterceptionTests()
|
||||
{
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<objects xmlns="http://www.springframework.net">
|
||||
|
||||
<object id="Spring.Util.MockControl" abstract="true">
|
||||
<object id="Spring.Web.Support.MockControl" abstract="true">
|
||||
<property name="GotIt" value="true" />
|
||||
</object>
|
||||
|
||||
Reference in New Issue
Block a user