Enabled support for nhibernate dynamic entities
fixed SPRNET-1174: Proxies dont implement methods of base interfaces of interfaces fixed SPRNET-1182: defer target==null checking until actual joinpoint invocation in proxy method implementations
This commit is contained in:
@@ -130,7 +130,9 @@ namespace Spring.Aop.Framework
|
||||
{
|
||||
#region Sanity Check
|
||||
|
||||
AssertUtils.ArgumentNotNull(target, "target");
|
||||
// EE: There is not necessarily always a target - e.g. for DynamicEntities
|
||||
// moved this check to InvokeJoinpoint()
|
||||
// AssertUtils.ArgumentNotNull(target, "target");
|
||||
AssertUtils.ArgumentNotNull(method, "method");
|
||||
|
||||
#endregion
|
||||
@@ -252,7 +254,8 @@ namespace Spring.Aop.Framework
|
||||
{
|
||||
if (this.interceptors == null ||
|
||||
this.currentInterceptorIndex == this.interceptors.Count)
|
||||
{
|
||||
{
|
||||
AssertJoinpoint();
|
||||
return InvokeJoinpoint();
|
||||
}
|
||||
object interceptor = this.interceptors[this.currentInterceptorIndex];
|
||||
@@ -296,6 +299,27 @@ namespace Spring.Aop.Framework
|
||||
protected abstract IMethodInvocation PrepareMethodInvocationForProceed(
|
||||
IMethodInvocation invocation);
|
||||
|
||||
/// <summary>
|
||||
/// Performs sanity checks, whether the actual joinpoint may be invoked
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default checks that the underlying target is not null and the called method is implemented
|
||||
/// by the target's type.
|
||||
/// </remarks>
|
||||
/// <exception cref="ArgumentNullException">if <see cref="target"/> is <c>null</c>.</exception>
|
||||
/// <exception cref="NotSupportedException">if the <see cref="target"/> 's type does not implement <see cref="method"/>.</exception>
|
||||
protected virtual void AssertJoinpoint()
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(target, "target");
|
||||
// if (this.method != null
|
||||
// && !this.method.DeclaringType.IsAssignableFrom(target.GetType()))
|
||||
// {
|
||||
// // This means the target type doesn't implement the interface.
|
||||
// // Since no interceptor has handled the call, we throw a sensible exception here.
|
||||
// throw new NotSupportedException(string.Format("Interface method '{0}.{1}()' was not handled by any interceptor and the underlying target type '{2}' does not implement this method.", method.DeclaringType.FullName, method.Name, target.GetType().FullName));
|
||||
// }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the joinpoint.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#region License
|
||||
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2005 the original author or authors.
|
||||
*
|
||||
@@ -14,85 +14,89 @@
|
||||
* 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 Spring.Util;
|
||||
using Spring.Reflection.Dynamic;
|
||||
using AopAlliance.Intercept;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Aop.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Invokes a target method using dynamic reflection.
|
||||
/// </summary>
|
||||
/// <seealso cref="Spring.Reflection.Dynamic.DynamicMethod"/>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
/// <author>Bruno Baia</author>
|
||||
[Serializable]
|
||||
public class DynamicMethodInvocation : AbstractMethodInvocation
|
||||
{
|
||||
/// <summary>
|
||||
/// The method invocation that is to be invoked on the proxy.
|
||||
/// </summary>
|
||||
protected MethodInfo proxyMethod;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Aop.Framework.DynamicMethodInvocation"/> class.
|
||||
/// </summary>
|
||||
/// <param name="proxy">The AOP proxy.</param>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <param name="method">The target method proxied.</param>
|
||||
/// <param name="proxyMethod">The method to invoke on proxy.</param>
|
||||
/// <param name="arguments">The target method's arguments.</param>
|
||||
/// <param name="targetType">
|
||||
/// The <see cref="System.Type"/> of the target object.</param>
|
||||
/// <param name="interceptors">
|
||||
/// The list of interceptors that are to be applied. May be
|
||||
/// <cref lang="null"/>.
|
||||
/// </param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If any of the <paramref name="target"/> or <paramref name="method"/>
|
||||
/// parameters is <see langword="null"/>.
|
||||
/// </exception>
|
||||
public DynamicMethodInvocation(
|
||||
object proxy, object target, MethodInfo method, MethodInfo proxyMethod,
|
||||
object[] arguments, Type targetType, IList interceptors)
|
||||
: base(proxy, target, method, arguments, targetType, interceptors)
|
||||
{
|
||||
this.proxyMethod = proxyMethod;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the joinpoint using dynamic reflection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Subclasses can override this to use custom invocation.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// The return value of the invocation of the joinpoint.
|
||||
/// </returns>
|
||||
/// <exception cref="System.Exception">
|
||||
/// If invoking the joinpoint resulted in an exception.
|
||||
/// </exception>
|
||||
/// <see cref="Spring.Aop.Framework.AbstractMethodInvocation.InvokeJoinpoint"/>
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
|
||||
using Spring.Util;
|
||||
using Spring.Reflection.Dynamic;
|
||||
using AopAlliance.Intercept;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Aop.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Invokes a target method using dynamic reflection.
|
||||
/// </summary>
|
||||
/// <seealso cref="Spring.Reflection.Dynamic.DynamicMethod"/>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
/// <author>Bruno Baia</author>
|
||||
[Serializable]
|
||||
public class DynamicMethodInvocation : AbstractMethodInvocation
|
||||
{
|
||||
/// <summary>
|
||||
/// The method invocation that is to be invoked on the proxy.
|
||||
/// </summary>
|
||||
protected MethodInfo proxyMethod;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Aop.Framework.DynamicMethodInvocation"/> class.
|
||||
/// </summary>
|
||||
/// <param name="proxy">The AOP proxy.</param>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <param name="method">The target method proxied.</param>
|
||||
/// <param name="proxyMethod">The method to invoke on proxy.</param>
|
||||
/// <param name="arguments">The target method's arguments.</param>
|
||||
/// <param name="targetType">
|
||||
/// The <see cref="System.Type"/> of the target object.</param>
|
||||
/// <param name="interceptors">
|
||||
/// The list of interceptors that are to be applied. May be
|
||||
/// <cref lang="null"/>.
|
||||
/// </param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If any of the <paramref name="target"/> or <paramref name="method"/>
|
||||
/// parameters is <see langword="null"/>.
|
||||
/// </exception>
|
||||
public DynamicMethodInvocation(
|
||||
object proxy, object target, MethodInfo method, MethodInfo proxyMethod,
|
||||
object[] arguments, Type targetType, IList interceptors)
|
||||
: base(proxy, target, method, arguments, targetType, interceptors)
|
||||
{
|
||||
this.proxyMethod = proxyMethod;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the joinpoint using dynamic reflection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Subclasses can override this to use custom invocation.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// The return value of the invocation of the joinpoint.
|
||||
/// </returns>
|
||||
/// <exception cref="System.Exception">
|
||||
/// If invoking the joinpoint resulted in an exception.
|
||||
/// </exception>
|
||||
/// <see cref="Spring.Aop.Framework.AbstractMethodInvocation.InvokeJoinpoint"/>
|
||||
protected override object InvokeJoinpoint()
|
||||
{
|
||||
IDynamicMethod targetMethod = (this.proxyMethod == null) ? new SafeMethod(method) : new SafeMethod(proxyMethod);
|
||||
try
|
||||
{
|
||||
{
|
||||
MethodInfo targetMethodInfo = ((this.proxyMethod == null)) ? method : this.proxyMethod;
|
||||
|
||||
IDynamicMethod targetMethod = new SafeMethod(targetMethodInfo);
|
||||
|
||||
try
|
||||
{
|
||||
AssertUtils.Understands(target, "target", targetMethodInfo);
|
||||
return targetMethod.Invoke(target, arguments);
|
||||
}
|
||||
// Only happens if fallback to standard reflection.
|
||||
@@ -100,26 +104,26 @@ namespace Spring.Aop.Framework
|
||||
{
|
||||
throw ReflectionUtils.UnwrapTargetInvocationException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="Spring.Aop.Framework.DynamicMethodInvocation"/> instance
|
||||
/// from the specified <see cref="AopAlliance.Intercept.IMethodInvocation"/> and
|
||||
/// increments the interceptor index.
|
||||
/// </summary>
|
||||
/// <param name="invocation">
|
||||
/// The current <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The new <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance to use.
|
||||
/// </returns>
|
||||
protected override IMethodInvocation PrepareMethodInvocationForProceed(IMethodInvocation invocation)
|
||||
{
|
||||
DynamicMethodInvocation rmi = new DynamicMethodInvocation(
|
||||
this.proxy, this.target, this.method, this.proxyMethod, this.arguments, this.targetType, this.interceptors);
|
||||
rmi.currentInterceptorIndex = this.currentInterceptorIndex + 1;
|
||||
|
||||
return rmi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="Spring.Aop.Framework.DynamicMethodInvocation"/> instance
|
||||
/// from the specified <see cref="AopAlliance.Intercept.IMethodInvocation"/> and
|
||||
/// increments the interceptor index.
|
||||
/// </summary>
|
||||
/// <param name="invocation">
|
||||
/// The current <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The new <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance to use.
|
||||
/// </returns>
|
||||
protected override IMethodInvocation PrepareMethodInvocationForProceed(IMethodInvocation invocation)
|
||||
{
|
||||
DynamicMethodInvocation rmi = new DynamicMethodInvocation(
|
||||
this.proxy, this.target, this.method, this.proxyMethod, this.arguments, this.targetType, this.interceptors);
|
||||
rmi.currentInterceptorIndex = this.currentInterceptorIndex + 1;
|
||||
|
||||
return rmi;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,21 +91,17 @@ namespace Spring.Aop.Framework
|
||||
protected override object InvokeJoinpoint()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (proxyMethod == null)
|
||||
{
|
||||
return method.Invoke(target, arguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
return proxyMethod.Invoke(target, arguments);
|
||||
}
|
||||
{
|
||||
MethodInfo targetMethodInfo = ((this.proxyMethod == null)) ? method : this.proxyMethod;
|
||||
|
||||
AssertUtils.Understands(target, "target", targetMethodInfo);
|
||||
return targetMethodInfo.Invoke(target, arguments);
|
||||
}
|
||||
catch (TargetInvocationException ex)
|
||||
{
|
||||
throw ReflectionUtils.UnwrapTargetInvocationException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="Spring.Aop.Framework.ReflectiveMethodInvocation"/> instance
|
||||
|
||||
@@ -275,7 +275,14 @@ namespace Spring.Proxy
|
||||
// setup target object for call
|
||||
PushTarget(il);
|
||||
|
||||
// cast to type method is on
|
||||
// TODO (EE): check for null and interface type and throw NotSupportedException
|
||||
LocalBuilder targetRef = il.DeclareLocal(typeof(object));
|
||||
il.Emit(OpCodes.Stloc, targetRef);
|
||||
|
||||
CallAssertUnderstands(il, interfaceMethod, targetRef, "target");
|
||||
|
||||
// setup target and cast to type method is on
|
||||
il.Emit(OpCodes.Ldloc, targetRef);
|
||||
il.Emit(OpCodes.Castclass, interfaceMethod.DeclaringType);
|
||||
|
||||
// setup parameters for call
|
||||
@@ -289,6 +296,17 @@ namespace Spring.Proxy
|
||||
il.EmitCall(OpCodes.Callvirt, interfaceMethod, null);
|
||||
}
|
||||
|
||||
private void CallAssertUnderstands(ILGenerator il, MethodInfo method, LocalBuilder targetRef, string targetName)
|
||||
{
|
||||
// AssertArgumentType
|
||||
il.Emit(OpCodes.Ldloc, targetRef);
|
||||
il.Emit(OpCodes.Ldstr, targetName);
|
||||
il.Emit(OpCodes.Ldtoken, method.DeclaringType);
|
||||
il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) }));
|
||||
// il.Emit(OpCodes.Ldstr, string.Format("Interface method '{0}.{1}()' was not handled by any interceptor and the target does not implement this method.", method.DeclaringType.FullName, method.Name));
|
||||
il.Emit(OpCodes.Call, typeof(AssertUtils).GetMethod("Understands", new Type[] { typeof(object), typeof(string), typeof(Type) }));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls base method directly.
|
||||
/// </summary>
|
||||
@@ -299,6 +317,16 @@ namespace Spring.Proxy
|
||||
// setup proxy instance for call
|
||||
PushProxy(il);
|
||||
|
||||
// TODO (EE): check for null and interface type and throw NotSupportedException
|
||||
LocalBuilder targetRef = il.DeclareLocal(typeof(object));
|
||||
il.Emit(OpCodes.Stloc, targetRef);
|
||||
|
||||
CallAssertUnderstands(il, method, targetRef, "base");
|
||||
|
||||
// setup target and cast to type method is on
|
||||
il.Emit(OpCodes.Ldloc, targetRef);
|
||||
il.Emit(OpCodes.Castclass, method.DeclaringType);
|
||||
|
||||
// setup parameters for call
|
||||
ParameterInfo[] paramArray = method.GetParameters();
|
||||
for (int i = 0; i < paramArray.Length; i++)
|
||||
@@ -343,6 +371,21 @@ namespace Spring.Proxy
|
||||
il.MarkLabel(jmpMethodReturn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates code that throws <see cref="InvalidOperationException"/>.
|
||||
/// </summary>
|
||||
/// <param name="il">IL generator to use.</param>
|
||||
/// <param name="exceptionType">the type of the exception to throw</param>
|
||||
/// <param name="message">Error message to use.</param>
|
||||
protected static void EmitThrowException(ILGenerator il, Type exceptionType, string message)
|
||||
{
|
||||
ConstructorInfo NewException = exceptionType.GetConstructor(new Type[] { typeof(string) });
|
||||
|
||||
il.Emit(OpCodes.Ldstr, message);
|
||||
il.Emit(OpCodes.Newobj, NewException);
|
||||
il.Emit(OpCodes.Throw);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ using System.Reflection.Emit;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
using Common.Logging;
|
||||
using Spring.Collections;
|
||||
using Spring.Core.TypeResolution;
|
||||
using Spring.Util;
|
||||
|
||||
@@ -964,7 +965,7 @@ namespace Spring.Proxy
|
||||
/// </returns>
|
||||
protected virtual Type[] GetProxiableInterfaces(Type[] interfaces)
|
||||
{
|
||||
ArrayList proxiableInterfaces = new ArrayList();
|
||||
ArrayList proxiableInterfaces = new ArrayList();
|
||||
|
||||
foreach(Type intf in interfaces)
|
||||
{
|
||||
@@ -972,7 +973,19 @@ namespace Spring.Proxy
|
||||
!IsSpecialInterface(intf) &&
|
||||
ReflectionUtils.IsTypeVisible(intf, DynamicProxyManager.ASSEMBLY_NAME))
|
||||
{
|
||||
proxiableInterfaces.Add(intf);
|
||||
if (!proxiableInterfaces.Contains(intf))
|
||||
{
|
||||
proxiableInterfaces.Add(intf);
|
||||
}
|
||||
|
||||
Type[] baseInterfaces = intf.GetInterfaces();
|
||||
foreach (Type baseInterface in baseInterfaces)
|
||||
{
|
||||
if (!proxiableInterfaces.Contains(baseInterface))
|
||||
{
|
||||
proxiableInterfaces.Add(baseInterface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,11 @@
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Remoting;
|
||||
using System.Runtime.Remoting.Proxies;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -37,9 +41,125 @@ namespace Spring.Util
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
/// <author>Erich Eichinger</author>
|
||||
public sealed class AssertUtils
|
||||
{
|
||||
/// <summary>
|
||||
///<summary>
|
||||
/// Checks, whether <paramref name="method"/> may be invoked on <paramref name="target"/>.
|
||||
/// Supports testing transparent proxies.
|
||||
///</summary>
|
||||
///<param name="target">the target instance or <c>null</c></param>
|
||||
///<param name="targetName">the name of the target to be used in error messages</param>
|
||||
///<param name="method">the method to test for</param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// if <paramref name="method"/> is <c>null</c>
|
||||
/// </exception>
|
||||
/// <exception cref="NotSupportedException">
|
||||
/// if it is not possible to invoke <paramref name="method"/> on <paramref name="target"/>
|
||||
/// </exception>
|
||||
public static void Understands(object target, string targetName, MethodBase method)
|
||||
{
|
||||
ArgumentNotNull(method, "method");
|
||||
|
||||
if (target==null )
|
||||
{
|
||||
if (method.IsStatic)
|
||||
{
|
||||
return;
|
||||
}
|
||||
throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "Target '{0}' is null and target method '{1}.{2}' is not static.", targetName, method.DeclaringType.FullName, method.Name));
|
||||
}
|
||||
|
||||
Understands(target, targetName, method.DeclaringType);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// checks, whether <paramref name="target"/> supports the methods of <paramref name="requiredType"/>.
|
||||
/// Supports testing transparent proxies.
|
||||
///</summary>
|
||||
///<param name="target">the target instance or <c>null</c></param>
|
||||
///<param name="targetName">the name of the target to be used in error messages</param>
|
||||
///<param name="requiredType">the type to test for</param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// if <paramref name="requiredType"/> is <c>null</c>
|
||||
/// </exception>
|
||||
/// <exception cref="NotSupportedException">
|
||||
/// if it is not possible to invoke methods of
|
||||
/// type <paramref name="requiredType"/> on <paramref name="target"/>
|
||||
/// </exception>
|
||||
public static void Understands(object target, string targetName, Type requiredType)
|
||||
{
|
||||
ArgumentNotNull(requiredType, "requiredType");
|
||||
|
||||
if (target == null)
|
||||
{
|
||||
throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "Target '{0}' is null.", targetName));
|
||||
}
|
||||
|
||||
Type targetType;
|
||||
if (RemotingServices.IsTransparentProxy(target))
|
||||
{
|
||||
RealProxy rp = RemotingServices.GetRealProxy(target);
|
||||
IRemotingTypeInfo rti = rp as IRemotingTypeInfo;
|
||||
if (rti != null)
|
||||
{
|
||||
if (rti.CanCastTo(requiredType, target))
|
||||
{
|
||||
return;
|
||||
}
|
||||
throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "Target '{0}' is a transparent proxy that does not support methods of '{1}'.", targetName, requiredType.FullName));
|
||||
}
|
||||
targetType = rp.GetProxiedType();
|
||||
}
|
||||
else
|
||||
{
|
||||
targetType = target.GetType();
|
||||
}
|
||||
|
||||
if (!requiredType.IsAssignableFrom(targetType))
|
||||
{
|
||||
throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "Target '{0}' of type '{1}' does not support methods of '{2}'.", targetName, targetType, requiredType.FullName));
|
||||
}
|
||||
}
|
||||
|
||||
#region checking casts on transparent proxies (From BCL via Reflector)
|
||||
// private static bool CheckCast(RealProxy rp, Type castType)
|
||||
// {
|
||||
// bool flag = false;
|
||||
// if (castType == typeof(object))
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
// if (!castType.IsInterface && !castType.IsMarshalByRef)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// if (castType != typeof(IObjectReference))
|
||||
// {
|
||||
// IRemotingTypeInfo typeInfo = rp as IRemotingTypeInfo;
|
||||
// if (typeInfo != null)
|
||||
// {
|
||||
// return typeInfo.CanCastTo(castType, rp.GetTransparentProxy());
|
||||
// }
|
||||
// Identity identityObject = rp.IdentityObject;
|
||||
// if (identityObject != null)
|
||||
// {
|
||||
// ObjRef objectRef = identityObject.ObjectRef;
|
||||
// if (objectRef != null)
|
||||
// {
|
||||
// typeInfo = objectRef.TypeInfo;
|
||||
// if (typeInfo != null)
|
||||
// {
|
||||
// flag = typeInfo.CanCastTo(castType, rp.GetTransparentProxy());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return flag;
|
||||
// }
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Checks the value of the supplied <paramref name="argument"/> and throws an
|
||||
/// <see cref="System.ArgumentNullException"/> if it is <see langword="null"/>.
|
||||
/// </summary>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,10 @@ using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using AopAlliance.Intercept;
|
||||
using DotNetMock.Dynamic;
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
using Spring.Aop.Interceptor;
|
||||
using Spring.Aop.Support;
|
||||
using Spring.Objects;
|
||||
|
||||
@@ -21,25 +21,29 @@
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.Remoting;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Runtime.Remoting.Proxies;
|
||||
using NUnit.Framework;
|
||||
using Spring.Objects;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the AssertUtils class.
|
||||
/// </summary>
|
||||
/// <author>Rick Evans</author>
|
||||
[TestFixture]
|
||||
public sealed class AssertUtilsTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the AssertUtils class.
|
||||
/// </summary>
|
||||
/// <author>Rick Evans</author>
|
||||
[TestFixture]
|
||||
public sealed class AssertUtilsTests
|
||||
{
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentException),ExpectedMessage = "foo")]
|
||||
[ExpectedException(typeof(ArgumentException), ExpectedMessage = "foo")]
|
||||
public void IsTrueWithMesssage()
|
||||
{
|
||||
AssertUtils.IsTrue(false,"foo");
|
||||
AssertUtils.IsTrue(false, "foo");
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -65,48 +69,48 @@ namespace Spring.Util
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void StateTrue()
|
||||
{
|
||||
AssertUtils.State(false,"foo");
|
||||
AssertUtils.State(false, "foo");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void ArgumentNotNull ()
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(null, "foo");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void ArgumentNotNullWithMessage ()
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(null, "foo", "Bang!");
|
||||
}
|
||||
public void ArgumentNotNull()
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(null, "foo");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ArgumentHasTextWithValidText()
|
||||
{
|
||||
AssertUtils.ArgumentHasText("... and no-one's getting fat 'cept Mama Cas!", "foo");
|
||||
}
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void ArgumentNotNullWithMessage()
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(null, "foo", "Bang!");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ArgumentHasTextWithValidTextAndMessage()
|
||||
{
|
||||
AssertUtils.ArgumentHasText("... and no-one's getting fat 'cept Mama Cas!", "foo", "Bang!");
|
||||
}
|
||||
[Test]
|
||||
public void ArgumentHasTextWithValidText()
|
||||
{
|
||||
AssertUtils.ArgumentHasText("... and no-one's getting fat 'cept Mama Cas!", "foo");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void ArgumentHasText ()
|
||||
{
|
||||
AssertUtils.ArgumentHasText(null, "foo");
|
||||
}
|
||||
[Test]
|
||||
public void ArgumentHasTextWithValidTextAndMessage()
|
||||
{
|
||||
AssertUtils.ArgumentHasText("... and no-one's getting fat 'cept Mama Cas!", "foo", "Bang!");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void ArgumentHasTextWithMessage ()
|
||||
{
|
||||
AssertUtils.ArgumentHasText(null, "foo", "Bang!");
|
||||
}
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void ArgumentHasText()
|
||||
{
|
||||
AssertUtils.ArgumentHasText(null, "foo");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void ArgumentHasTextWithMessage()
|
||||
{
|
||||
AssertUtils.ArgumentHasText(null, "foo", "Bang!");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
@@ -174,5 +178,110 @@ namespace Spring.Util
|
||||
{
|
||||
AssertUtils.ArgumentHasElements(new object[] { new object(), new object(), new object() }, "foo");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnderstandsType()
|
||||
{
|
||||
MethodInfo getDescriptionMethod = typeof(ITestObject).GetMethod("GetDescription", new Type[0]);
|
||||
MethodInfo understandsMethod = typeof(AssertUtils).GetMethod("Understands", BindingFlags.Public|BindingFlags.Static, null, new Type[] {typeof (object), typeof(string), typeof (MethodBase)}, null);
|
||||
|
||||
// null target, any type
|
||||
AssertNotUnderstandsType(null, "target", typeof(object), typeof(NotSupportedException), "Target 'target' is null.");
|
||||
// any target, null type
|
||||
AssertNotUnderstandsType(new object(), "target", null, typeof(ArgumentNullException), "Argument 'requiredType' cannot be null.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnderstandsMethod()
|
||||
{
|
||||
MethodInfo getDescriptionMethod = typeof(ITestObject).GetMethod("GetDescription", new Type[0]);
|
||||
MethodInfo understandsMethod = typeof(AssertUtils).GetMethod("Understands", BindingFlags.Public|BindingFlags.Static, null, new Type[] {typeof (object), typeof(string), typeof (MethodBase)}, null);
|
||||
|
||||
// null target, static method
|
||||
AssertUtils.Understands(null, "target", understandsMethod);
|
||||
// null target, instance method
|
||||
AssertNotUnderstandsMethod(null, "target", getDescriptionMethod, typeof(NotSupportedException), "Target 'target' is null and target method 'Spring.Objects.ITestObject.GetDescription' is not static.");
|
||||
// compatible target, instance method
|
||||
AssertUtils.Understands(new TestObject(), "target", getDescriptionMethod);
|
||||
// incompatible target, instance method
|
||||
AssertNotUnderstandsMethod(new object(), "target", getDescriptionMethod, typeof(NotSupportedException), "Target 'target' of type 'System.Object' does not support methods of 'Spring.Objects.ITestObject'.");
|
||||
// compatible transparent proxy, instance method
|
||||
object compatibleProxy = new TestProxy(new TestObject()).GetTransparentProxy();
|
||||
AssertUtils.Understands(compatibleProxy, "compatibleProxy", getDescriptionMethod);
|
||||
// incompatible transparent proxy, instance method
|
||||
object incompatibleProxy = new TestProxy(new object()).GetTransparentProxy();
|
||||
AssertNotUnderstandsMethod(incompatibleProxy, "incompatibleProxy", getDescriptionMethod, typeof(NotSupportedException), "Target 'incompatibleProxy' is a transparent proxy that does not support methods of 'Spring.Objects.ITestObject'.");
|
||||
}
|
||||
|
||||
private void AssertNotUnderstandsType(object target, string targetName, Type requiredType, Type exceptionType, string partialMessage)
|
||||
{
|
||||
try
|
||||
{
|
||||
AssertUtils.Understands(target, targetName, requiredType);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
if (ex.GetType() != exceptionType)
|
||||
{
|
||||
Assert.Fail("Expected Exception of type {0}, but was {1}", exceptionType, ex.GetType());
|
||||
}
|
||||
|
||||
if (-1 == ex.Message.IndexOf(partialMessage))
|
||||
{
|
||||
Assert.Fail("Expected Message '{0}', but got '{1}'", partialMessage, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AssertNotUnderstandsMethod(object target, string targetName, MethodBase method, Type exceptionType, string partialMessage)
|
||||
{
|
||||
try
|
||||
{
|
||||
AssertUtils.Understands(target, targetName, method);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
if (ex.GetType() != exceptionType)
|
||||
{
|
||||
Assert.Fail("Expected Exception of type {0}, but was {1}", exceptionType, ex.GetType());
|
||||
}
|
||||
|
||||
if (-1 == ex.Message.IndexOf(partialMessage))
|
||||
{
|
||||
Assert.Fail("Expected Message '{0}', but got '{1}'", partialMessage, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class TestProxy : RealProxy, IRemotingTypeInfo
|
||||
{
|
||||
private readonly object targetInstance;
|
||||
|
||||
public TestProxy(object targetInstance)
|
||||
: base(typeof(MarshalByRefObject))
|
||||
{
|
||||
this.targetInstance = targetInstance;
|
||||
}
|
||||
|
||||
public override IMessage Invoke(IMessage msg)
|
||||
{
|
||||
// return new ReturnMessage(result, null, 0, null, callMsg);
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public bool CanCastTo(Type fromType, object o)
|
||||
{
|
||||
bool res = fromType.IsAssignableFrom(targetInstance.GetType());
|
||||
return res;
|
||||
}
|
||||
|
||||
public string TypeName
|
||||
{
|
||||
get { return targetInstance.GetType().AssemblyQualifiedName; }
|
||||
set { throw new System.NotSupportedException(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user