User: xtoff
Date: 2009/11/14 12:12 PM

Removed:
 /DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/
  ProxyMethod.cs

Modified:
 /DynamicProxy/trunk/lib/mono-3.5/
  Castle.Core.dll, Castle.Core.xml
 /DynamicProxy/trunk/lib/net-2.0/
  Castle.Core.dll, Castle.Core.xml
 /DynamicProxy/trunk/lib/net-3.5/
  Castle.Core.dll, Castle.Core.xml
 /DynamicProxy/trunk/lib/silverlight-2.0/
  Castle.Core.dll, Castle.Core.xml
 /DynamicProxy/trunk/src/Castle.DynamicProxy/
  AbstractInvocation.cs
 /DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/
  InvocationTypeGenerator.cs
 /DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/
  InvocationMethods.cs

Log:
 - BREAKING CHANGE - implemented DYNPROXY-ISSUE-91 - Allow 
CreateInterfaceProxyWithTargetInterface to be able to permanently change 
target. This required adding a method to IChangeProxyTarget interface from 
Castle.Core so any code that implements this interface explicitly will not 
compile. This is a low-impact change however, since this interface is not 
intended to be implemented by users.

File Changes:

Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/
=======================================================

File [modified]: AbstractInvocation.cs
Delta lines: +41 -10
===================================================================

--- 
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InvocationTypeGenerator.cs
    2009-11-14 18:51:50 UTC (rev 6326)
+++ 
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InvocationTypeGenerator.cs
    2009-11-14 19:12:50 UTC (rev 6327)
@@ -65,16 +65,7 @@
                        var targetField = new 
FieldReference(InvocationMethods.Target);
                        if (canChangeTarget)
                        {
-                               var argument1 = new ArgumentReference(typeof 
(object));
-                               MethodEmitter methodEmitter =
-                                       
nested.CreateMethod("ChangeInvocationTarget", MethodAttributes.Public | 
MethodAttributes.Virtual,
-                                                           typeof (void), 
argument1);
-                               methodEmitter.CodeBuilder.AddStatement(
-                                       new AssignStatement(targetField,
-                                                           new 
ConvertExpression(targetType, argument1.ToExpression())
-                                               )
-                                       );
-                               methodEmitter.CodeBuilder.AddStatement(new 
ReturnStatement());
+                               ImplementChangeProxyTargetInterface(@class, 
nested, targetField);
                        }
 
                        // InvokeMethodOnTarget implementation
@@ -99,6 +90,46 @@
                        return nested;
                }
 
+               private void ImplementChangeProxyTargetInterface(ClassEmitter 
@class, NestedClassEmitter invocation, FieldReference targetField)
+               {
+                       ImplementChangeInvocationTarget(invocation, 
targetField);
+
+                       ImplementChangeProxyTarget(invocation, @class);
+               }
+
+               private void ImplementChangeProxyTarget(NestedClassEmitter 
invocation, ClassEmitter @class)
+               {
+                       var argument = new ArgumentReference(typeof(object));
+                       var changeInvocationTarget = 
invocation.CreateMethod("ChangeProxyTarget",
+                                                                            
MethodAttributes.Public | MethodAttributes.Virtual,
+                                                                            
typeof(void),
+                                                                            
argument);
+                       changeInvocationTarget.CodeBuilder.AddStatement(
+                               new ExpressionStatement(
+                                       new 
ConvertExpression(@class.TypeBuilder, new 
FieldReference(InvocationMethods.ProxyObject).ToExpression())));
+
+                       var field = @class.GetField("__target");
+                       changeInvocationTarget.CodeBuilder.AddStatement(
+                               new AssignStatement(
+                                       new FieldReference(field.Reference) { 
OwnerReference = null },
+                                       new 
ConvertExpression(field.Fieldbuilder.FieldType, argument.ToExpression())));
+
+                       changeInvocationTarget.CodeBuilder.AddStatement(new 
ReturnStatement());
+               }
+
+               private void ImplementChangeInvocationTarget(NestedClassEmitter 
invocation, FieldReference targetField)
+               {
+                       var argument = new ArgumentReference(typeof (object));
+                       var changeInvocationTarget = 
invocation.CreateMethod("ChangeInvocationTarget",
+                                                                            
MethodAttributes.Public | MethodAttributes.Virtual,
+                                                                            
typeof(void),
+                                                                            
argument);
+                       changeInvocationTarget.CodeBuilder.AddStatement(
+                               new AssignStatement(targetField,
+                                                   new 
ConvertExpression(targetType, argument.ToExpression())));
+                       changeInvocationTarget.CodeBuilder.AddStatement(new 
ReturnStatement());
+               }
+
                protected void 
CreateIInvocationInvokeOnTarget(NestedClassEmitter nested, ParameterInfo[] 
parameters, FieldReference targetField, MethodInfo callbackMethod)
                {

Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/
==================================================================

File [modified]: InvocationTypeGenerator.cs
Delta lines: +0 -32
===================================================================

--- DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/ProxyMethod.cs        
2009-11-14 18:51:50 UTC (rev 6326)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/ProxyMethod.cs        
2009-11-14 19:12:50 UTC (rev 6327)
@@ -1,32 +0,0 @@
-namespace Castle.DynamicProxy.Generators
-{
-       using System.Reflection;
-       using Contributors;
-
-       public abstract class ProxyMethod : IProxyMethod
-       {
-               private readonly MethodInfo method;
-               private readonly ITypeContributor target;
-
-               protected ProxyMethod(MethodInfo method, ITypeContributor 
target)
-               {
-                       this.method = method;
-                       this.target = target;
-               }
-
-               public MethodInfo Method
-               {
-                       get { return method; }
-               }
-
-               public bool HasTarget
-               {
-                       get
-                       {
-                               return target != null;
-                       }
-               }
-
-               public abstract MethodInfo MethodOnTarget { get; }
-       }
-}

File [removed]: ProxyMethod.cs
Delta lines: +4 -1
===================================================================

--- DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/InvocationMethods.cs      
2009-11-14 18:51:50 UTC (rev 6326)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/InvocationMethods.cs      
2009-11-14 19:12:50 UTC (rev 6327)
@@ -26,12 +26,16 @@
                public static readonly FieldInfo Target =
                        typeof(AbstractInvocation).GetField("target", 
BindingFlags.Instance | BindingFlags.NonPublic);
 
+               public static readonly FieldInfo ProxyObject =
+                       typeof(AbstractInvocation).GetField("proxyObject", 
BindingFlags.Instance | BindingFlags.NonPublic);
+
                public static readonly MethodInfo GetArguments =
                        typeof(AbstractInvocation).GetMethod("get_Arguments");
 
                public static readonly MethodInfo GetArgumentValue =
                        
typeof(AbstractInvocation).GetMethod("GetArgumentValue");
 
+
                public static readonly MethodInfo GetReturnValue =
                        typeof(AbstractInvocation).GetMethod("get_ReturnValue");
 
@@ -62,7 +66,6 @@
                                                                  new[]
                                                                  {
                                                                        
typeof(object),
-
                                                                        
typeof(Type),
                                                                        
typeof(object),

Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/Tokens/
==============================================================

File [modified]: InvocationMethods.cs
Delta lines: +0 -0
===================================================================

Directory: /DynamicProxy/trunk/lib/mono-3.5/
============================================

File [modified]: Castle.Core.dll
Delta lines: None
None
File [modified]: Castle.Core.xml
Delta lines: +33 -0
===================================================================

--- DynamicProxy/trunk/lib/net-2.0/Castle.Core.xml      2009-11-14 18:51:50 UTC 
(rev 6326)
+++ DynamicProxy/trunk/lib/net-2.0/Castle.Core.xml      2009-11-14 19:12:50 UTC 
(rev 6327)
@@ -239,6 +239,39 @@
             it is illegal to return null, and doing so will result in 
exception.
             </remarks>
         </member>
+        <member name="T:Castle.Core.Interceptor.IChangeProxyTarget">
+            <summary>
+            Exposes means to change target objects of proxies and invocations
+            </summary>
+        </member>
+        <member 
name="M:Castle.Core.Interceptor.IChangeProxyTarget.ChangeInvocationTarget(System.Object)">
+            <summary>
+            Changes the target object (<see 
cref="P:Castle.Core.Interceptor.IInvocation.InvocationTarget"/>) of current 
<see cref="T:Castle.Core.Interceptor.IInvocation"/>.
+            </summary>
+            <param name="target">The new value of target of invocation.</param>
+            <remarks>
+            Although the method takes <see cref="T:System.Object"/> the actual 
instance must be of type assignable to <see 
cref="P:Castle.Core.Interceptor.IInvocation.TargetType"/>, otherwise an <see 
cref="T:System.InvalidCastException"/> will be thrown.
+            Also while it's technically legal to pass null reference (Nothing 
in Visual Basic) as <paramref name="target"/>, for obvious reasons Dynamic 
Proxy will not be able to call the intercepted method on such target.
+            In this case last interceptor in the pipeline mustn't call <see 
cref="M:Castle.Core.Interceptor.IInvocation.Proceed"/> or a <see 
cref="T:System.NotImplementedException"/> will be throws.
+            Also while it's technically legal to pass proxy itself as 
<paramref name="target"/>, this would create stack overflow.
+            In this case last interceptor in the pipeline mustn't call <see 
cref="M:Castle.Core.Interceptor.IInvocation.Proceed"/> or a <see 
cref="T:System.InvalidOperationException"/> will be throws.
+            </remarks>
+            <exception cref="T:System.InvalidCastException">Thrown when 
<paramref name="target"/> is not assignable to the proxied type.</exception>
+        </member>
+        <member 
name="M:Castle.Core.Interceptor.IChangeProxyTarget.ChangeProxyTarget(System.Object)">
+            <summary>
+            Permanently changes the target object of the proxy. This does not 
affect target of the current invocation.
+            </summary>
+            <param name="target">The new value of target of the proxy.</param>
+            <remarks>
+            Although the method takes <see cref="T:System.Object"/> the actual 
instance must be of type assignable to proxy's target type, otherwise an <see 
cref="T:System.InvalidCastException"/> will be thrown.
+            Also while it's technically legal to pass null reference (Nothing 
in Visual Basic) as <paramref name="target"/>, for obvious reasons Dynamic 
Proxy will not be able to call the intercepted method on such target.
+            In this case last interceptor in the pipeline mustn't call <see 
cref="M:Castle.Core.Interceptor.IInvocation.Proceed"/> or a <see 
cref="T:System.NotImplementedException"/> will be throws.
+            Also while it's technically legal to pass proxy itself as 
<paramref name="target"/>, this would create stack overflow.
+            In this case last interceptor in the pipeline mustn't call <see 
cref="M:Castle.Core.Interceptor.IInvocation.Proceed"/> or a <see 
cref="T:System.InvalidOperationException"/> will be throws.
+            </remarks>
+            <exception cref="T:System.InvalidCastException">Thrown when 
<paramref name="target"/> is not assignable to the proxied type.</exception>
+        </member>
         <member name="T:Castle.Core.Interceptor.IInterceptor">
             <summary>

Directory: /DynamicProxy/trunk/lib/net-2.0/
===========================================

File [modified]: Castle.Core.dll
Delta lines: None
None
File [modified]: Castle.Core.xml
Delta lines: +33 -0
===================================================================

--- DynamicProxy/trunk/lib/net-3.5/Castle.Core.xml      2009-11-14 18:51:50 UTC 
(rev 6326)
+++ DynamicProxy/trunk/lib/net-3.5/Castle.Core.xml      2009-11-14 19:12:50 UTC 
(rev 6327)
@@ -239,6 +239,39 @@
             it is illegal to return null, and doing so will result in 
exception.
             </remarks>
         </member>
+        <member name="T:Castle.Core.Interceptor.IChangeProxyTarget">
+            <summary>
+            Exposes means to change target objects of proxies and invocations
+            </summary>
+        </member>
+        <member 
name="M:Castle.Core.Interceptor.IChangeProxyTarget.ChangeInvocationTarget(System.Object)">
+            <summary>
+            Changes the target object (<see 
cref="P:Castle.Core.Interceptor.IInvocation.InvocationTarget"/>) of current 
<see cref="T:Castle.Core.Interceptor.IInvocation"/>.
+            </summary>
+            <param name="target">The new value of target of invocation.</param>
+            <remarks>
+            Although the method takes <see cref="T:System.Object"/> the actual 
instance must be of type assignable to <see 
cref="P:Castle.Core.Interceptor.IInvocation.TargetType"/>, otherwise an <see 
cref="T:System.InvalidCastException"/> will be thrown.
+            Also while it's technically legal to pass null reference (Nothing 
in Visual Basic) as <paramref name="target"/>, for obvious reasons Dynamic 
Proxy will not be able to call the intercepted method on such target.
+            In this case last interceptor in the pipeline mustn't call <see 
cref="M:Castle.Core.Interceptor.IInvocation.Proceed"/> or a <see 
cref="T:System.NotImplementedException"/> will be throws.
+            Also while it's technically legal to pass proxy itself as 
<paramref name="target"/>, this would create stack overflow.
+            In this case last interceptor in the pipeline mustn't call <see 
cref="M:Castle.Core.Interceptor.IInvocation.Proceed"/> or a <see 
cref="T:System.InvalidOperationException"/> will be throws.
+            </remarks>
+            <exception cref="T:System.InvalidCastException">Thrown when 
<paramref name="target"/> is not assignable to the proxied type.</exception>
+        </member>
+        <member 
name="M:Castle.Core.Interceptor.IChangeProxyTarget.ChangeProxyTarget(System.Object)">
+            <summary>
+            Permanently changes the target object of the proxy. This does not 
affect target of the current invocation.
+            </summary>
+            <param name="target">The new value of target of the proxy.</param>
+            <remarks>
+            Although the method takes <see cref="T:System.Object"/> the actual 
instance must be of type assignable to proxy's target type, otherwise an <see 
cref="T:System.InvalidCastException"/> will be thrown.
+            Also while it's technically legal to pass null reference (Nothing 
in Visual Basic) as <paramref name="target"/>, for obvious reasons Dynamic 
Proxy will not be able to call the intercepted method on such target.
+            In this case last interceptor in the pipeline mustn't call <see 
cref="M:Castle.Core.Interceptor.IInvocation.Proceed"/> or a <see 
cref="T:System.NotImplementedException"/> will be throws.
+            Also while it's technically legal to pass proxy itself as 
<paramref name="target"/>, this would create stack overflow.
+            In this case last interceptor in the pipeline mustn't call <see 
cref="M:Castle.Core.Interceptor.IInvocation.Proceed"/> or a <see 
cref="T:System.InvalidOperationException"/> will be throws.
+            </remarks>
+            <exception cref="T:System.InvalidCastException">Thrown when 
<paramref name="target"/> is not assignable to the proxied type.</exception>
+        </member>
         <member name="T:Castle.Core.Interceptor.IInterceptor">
             <summary>

Directory: /DynamicProxy/trunk/lib/net-3.5/
===========================================

File [modified]: Castle.Core.dll
Delta lines: None
None
File [modified]: Castle.Core.xml
Delta lines: +33 -0
===================================================================

--- DynamicProxy/trunk/lib/silverlight-2.0/Castle.Core.xml      2009-11-14 
18:51:50 UTC (rev 6326)
+++ DynamicProxy/trunk/lib/silverlight-2.0/Castle.Core.xml      2009-11-14 
19:12:50 UTC (rev 6327)
@@ -239,6 +239,39 @@
             it is illegal to return null, and doing so will result in 
exception.
             </remarks>
         </member>
+        <member name="T:Castle.Core.Interceptor.IChangeProxyTarget">
+            <summary>
+            Exposes means to change target objects of proxies and invocations
+            </summary>
+        </member>
+        <member 
name="M:Castle.Core.Interceptor.IChangeProxyTarget.ChangeInvocationTarget(System.Object)">
+            <summary>
+            Changes the target object (<see 
cref="P:Castle.Core.Interceptor.IInvocation.InvocationTarget"/>) of current 
<see cref="T:Castle.Core.Interceptor.IInvocation"/>.
+            </summary>
+            <param name="target">The new value of target of invocation.</param>
+            <remarks>
+            Although the method takes <see cref="T:System.Object"/> the actual 
instance must be of type assignable to <see 
cref="P:Castle.Core.Interceptor.IInvocation.TargetType"/>, otherwise an <see 
cref="T:System.InvalidCastException"/> will be thrown.
+            Also while it's technically legal to pass null reference (Nothing 
in Visual Basic) as <paramref name="target"/>, for obvious reasons Dynamic 
Proxy will not be able to call the intercepted method on such target.
+            In this case last interceptor in the pipeline mustn't call <see 
cref="M:Castle.Core.Interceptor.IInvocation.Proceed"/> or a <see 
cref="T:System.NotImplementedException"/> will be throws.
+            Also while it's technically legal to pass proxy itself as 
<paramref name="target"/>, this would create stack overflow.
+            In this case last interceptor in the pipeline mustn't call <see 
cref="M:Castle.Core.Interceptor.IInvocation.Proceed"/> or a <see 
cref="T:System.InvalidOperationException"/> will be throws.
+            </remarks>
+            <exception cref="T:System.InvalidCastException">Thrown when 
<paramref name="target"/> is not assignable to the proxied type.</exception>
+        </member>
+        <member 
name="M:Castle.Core.Interceptor.IChangeProxyTarget.ChangeProxyTarget(System.Object)">
+            <summary>
+            Permanently changes the target object of the proxy. This does not 
affect target of the current invocation.
+            </summary>
+            <param name="target">The new value of target of the proxy.</param>
+            <remarks>
+            Although the method takes <see cref="T:System.Object"/> the actual 
instance must be of type assignable to proxy's target type, otherwise an <see 
cref="T:System.InvalidCastException"/> will be thrown.
+            Also while it's technically legal to pass null reference (Nothing 
in Visual Basic) as <paramref name="target"/>, for obvious reasons Dynamic 
Proxy will not be able to call the intercepted method on such target.
+            In this case last interceptor in the pipeline mustn't call <see 
cref="M:Castle.Core.Interceptor.IInvocation.Proceed"/> or a <see 
cref="T:System.NotImplementedException"/> will be throws.
+            Also while it's technically legal to pass proxy itself as 
<paramref name="target"/>, this would create stack overflow.
+            In this case last interceptor in the pipeline mustn't call <see 
cref="M:Castle.Core.Interceptor.IInvocation.Proceed"/> or a <see 
cref="T:System.InvalidOperationException"/> will be throws.
+            </remarks>
+            <exception cref="T:System.InvalidCastException">Thrown when 
<paramref name="target"/> is not assignable to the proxied type.</exception>
+        </member>
         <member name="T:Castle.Core.Interceptor.IInterceptor">
             <summary>

Directory: /DynamicProxy/trunk/lib/silverlight-2.0/
===================================================

File [modified]: Castle.Core.dll
Delta lines: None
None
File [modified]: Castle.Core.xml
Delta lines: +21 -5
===================================================================

--- DynamicProxy/trunk/src/Castle.DynamicProxy/AbstractInvocation.cs    
2009-11-14 18:51:50 UTC (rev 6326)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/AbstractInvocation.cs    
2009-11-14 19:12:50 UTC (rev 6327)
@@ -27,7 +27,6 @@
        public abstract class AbstractInvocation : IInvocation, ISerializable
 #endif
        {
-               private readonly object proxy;
                private readonly IInterceptor[] interceptors;
                private readonly MethodInfo proxiedMethod;
                private readonly object[] arguments;
@@ -35,6 +34,7 @@
                private object returnValue;
                private int execIndex = -1;
                private Type[] genericMethodArguments;
+               protected readonly object proxyObject;
                protected object target;
 
                protected AbstractInvocation(
@@ -48,7 +48,7 @@
                        Debug.Assert(proxiedMethod != null);
                        this.target = target;
                        this.targetType = targetType;
-                       this.proxy = proxy;
+                       this.proxyObject = proxy;
                        this.interceptors = interceptors;
                        this.proxiedMethod = proxiedMethod;
                        this.arguments = arguments;
@@ -82,7 +82,7 @@
                                throw new NotImplementedException(message);
                        }
 
-                       if (!ReferenceEquals(target, proxy))
+                       if (!ReferenceEquals(target, proxyObject))
                        {
                                return;
                        }
@@ -92,11 +92,27 @@
                        throw new InvalidOperationException(message);
                }
 
+               protected void EnsureValidProxyTarget(object target)
+               {
+                       if (target == null)
+                       {
+                               throw new ArgumentNullException("target");
+                       }
+
+                       if (!ReferenceEquals(target, proxyObject))
+                       {
+                               return;
+                       }
+                       var message = "This is a DynamicProxy2 error: target of 
proxy has been set to the proxy itself. " +
+                                     "This would result in recursively calling 
proxy methods over and over again until stack overflow, which may destabilize 
your program." +
+                                     "This usually signifies a bug in the 
calling code. Make sure no interceptor sets proxy as its own target.";
+                       throw new InvalidOperationException(message);
+               }
+
                private IInterceptor[] 
SelectMethodInterceptors(IInterceptorSelector selector, IInterceptor[] 
methodInterceptors)
                {
                        if (methodInterceptors == null)
                        {
-                               //NOTE: perhaps instead of passing this.Method 
we should call this.GetConcreteMethod()
                                methodInterceptors = 
selector.SelectInterceptors(TargetType, Method, interceptors) ??
                                                     new IInterceptor[0];
                        }
@@ -115,7 +131,7 @@
 
                public object Proxy
                {
-                       get { return proxy; }
+                       get { return proxyObject; }
                }
 

--

You received this message because you are subscribed to the Google Groups 
"Castle Project Commits" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/castle-project-commits?hl=.


Reply via email to