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:
eeichinger
2009-03-08 12:58:06 +00:00
parent dfd93d42c3
commit c161b030ca
9 changed files with 941 additions and 433 deletions

View File

@@ -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>

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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>

View File

@@ -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;

View File

@@ -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(); }
}
}
}
}