User: xtoff
Date: 2009/11/13 09:21 AM
Modified:
/DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/
InterceptorSelectorTestCase.cs, InterfaceProxyWithTargetInterfaceTestCase.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Interfaces/
Two.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/
Castle.DynamicProxy-vs2008.csproj, ProxyGenerator.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/
InterfaceProxyWithoutTargetContributor.cs, MixinContributor.cs,
MixinContributorBase.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/
ClassProxyGenerator.cs, InterfaceProxyWithTargetGenerator.cs,
InterfaceProxyWithTargetInterfaceGenerator.cs,
InterfaceProxyWithoutTargetGenerator.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/Emitters/SimpleAST/
NullCoalescingOperatorExpression.cs
Log:
- fixed DYNPROXY-ISSUE-121 - "proxy with target interface incorrectly forwards
to mixins"
- added ability to change proxy target on mixin methods on interface proxy
with target interface
- added generic overloads for CreateInterfaceProxyWithTargetInterface to make
it consistent with other methods
File Changes:
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/
=======================================================
File [modified]: Castle.DynamicProxy-vs2008.csproj
Delta lines: +5 -10
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/InterfaceProxyWithoutTargetContributor.cs
2009-11-12 20:58:14 UTC (rev 6319)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/InterfaceProxyWithoutTargetContributor.cs
2009-11-13 16:21:11 UTC (rev 6320)
@@ -3,20 +3,21 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
- using System.Reflection;
+
using Castle.DynamicProxy.Generators;
using Castle.DynamicProxy.Generators.Emitters;
- using Castle.DynamicProxy.Generators.Emitters.SimpleAST;
public class InterfaceProxyWithoutTargetContributor : ITypeContributor
{
private readonly IList<MembersCollector> targets = new
List<MembersCollector>();
private readonly IList<Type> interfaces = new List<Type>();
private readonly INamingScope namingScope;
+ private readonly GetTargetExpressionDelegate
getTargetExpressionDelegate;
- public InterfaceProxyWithoutTargetContributor(INamingScope
namingScope)
+ public InterfaceProxyWithoutTargetContributor(INamingScope
namingScope, GetTargetExpressionDelegate getTarget)
{
this.namingScope = namingScope;
+ getTargetExpressionDelegate = getTarget;
}
public void CollectElementsToProxy(IProxyGenerationHook hook)
@@ -112,7 +113,7 @@
invocation,
@class.GetField("__interceptors"),
createMethod,
-
GetTargetExpression);
+
getTargetExpressionDelegate);
}
else
{
@@ -125,11 +126,5 @@
proxiedMethod.DefineCustomAttribute(attribute);
}
}
-
-
- protected virtual Expression GetTargetExpression(ClassEmitter
@class, MethodInfo method)
- {
- return NullExpression.Instance;
- }
}
}
File [modified]: ProxyGenerator.cs
Delta lines: +20 -1
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/InterceptorSelectorTestCase.cs
2009-11-12 20:58:14 UTC (rev 6319)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/InterceptorSelectorTestCase.cs
2009-11-13 16:21:11 UTC (rev 6320)
@@ -17,6 +17,9 @@
using System;
using System.Collections.Generic;
using System.Reflection;
+
+ using Castle.DynamicProxy.Tests.Interfaces;
+
using Core.Interceptor;
using Interceptors;
using NUnit.Framework;
@@ -126,9 +129,25 @@
Assert.AreEqual(5, result);
Assert.AreEqual(1, countingInterceptor.Count);
}
+
+ [Test]
+ [Ignore("DYNPROXY-ISSUE-122")]
+ public void
When_two_selectors_present_and_not_equal_should_cache_type_anyway()
+ {
+ var options1 = new ProxyGenerationOptions { Selector =
new AllInterceptorSelector() };
+ var options2 = new ProxyGenerationOptions
+ {
+ Selector = new
TypeInterceptorSelector<CallCountingInterceptor>()
+ };
+
+ var type1 =
generator.CreateInterfaceProxyWithTargetInterface<IOne>(new One(),
options1).GetType();
+ var type2 =
generator.CreateInterfaceProxyWithTargetInterface<IOne>(new One(),
options2).GetType();
+
+ Assert.AreSame(type1, type2);
+ }
}
-#if !MONO
+#if !MONO
public class MultiGenericClass : IMultiGenericInterface
{
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/
=============================================================
File [modified]: InterceptorSelectorTestCase.cs
Delta lines: +16 -1
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/InterfaceProxyWithTargetInterfaceTestCase.cs
2009-11-12 20:58:14 UTC (rev 6319)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/InterfaceProxyWithTargetInterfaceTestCase.cs
2009-11-13 16:21:11 UTC (rev 6320)
@@ -16,6 +16,7 @@
{
using System;
+ using Castle.DynamicProxy.Tests.Interceptors;
using Castle.DynamicProxy.Tests.Interfaces;
using Core.Interceptor;
@@ -57,7 +58,6 @@
}
[Test]
- [Ignore("DYNPROXY-ISSUE-121")]
public void
Mixin_methods_should_be_forwarded_to_target_if_implements_mixin_interface()
{
var options = new ProxyGenerationOptions();
@@ -69,5 +69,20 @@
Assert.AreEqual(2, result);
}
+ [Test]
+ public void
Invocation_should_be_IChangeInvocationTarget_for_Mixin_methods()
+ {
+ var options = new ProxyGenerationOptions();
+ options.AddMixinInstance(new Two());
+ var interceptor = new ChangeTargetInterceptor(new
OneTwo());
+ var proxy =
generator.CreateInterfaceProxyWithTargetInterface(typeof(IOne),
+
new One(),
+
options,
+
interceptor);
+
+ var result = (proxy as ITwo).TwoMethod();
+
+ Assert.AreEqual(2, result);
+ }
}
File [modified]: InterfaceProxyWithTargetInterfaceTestCase.cs
Delta lines: +3 -0
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Interfaces/Two.cs
2009-11-12 20:58:14 UTC (rev 6319)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Interfaces/Two.cs
2009-11-13 16:21:11 UTC (rev 6320)
@@ -14,6 +14,9 @@
namespace Castle.DynamicProxy.Tests.Interfaces
{
+ using System;
+
+ [Serializable]
public class Two : ITwo
{
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/
====================================================================
File [modified]: InterfaceProxyWithoutTargetContributor.cs
Delta lines: +17 -13
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/MixinContributor.cs
2009-11-12 20:58:14 UTC (rev 6319)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/MixinContributor.cs
2009-11-13 16:21:11 UTC (rev 6320)
@@ -16,30 +16,29 @@
{
using System;
using System.Diagnostics;
- using System.Reflection;
+
using Castle.DynamicProxy.Generators;
using Castle.DynamicProxy.Generators.Emitters;
public class MixinContributor : MixinContributorBase
{
- private const bool CanChangeTarget = false;
- private readonly InterfaceMapping mapping;
+ private readonly bool canChangeTarget;
private readonly INamingScope namingScope;
private MembersCollector target;
- public MixinContributor(Type targetType,Type @interface,
INamingScope namingScope)
+ public MixinContributor(Type @interface, INamingScope
namingScope)
+ : this(@interface, namingScope, false)
{
- if (targetType == null) throw new
ArgumentNullException("targetType");
+ }
+
+ public MixinContributor(Type @interface, INamingScope
namingScope, bool canChangeTarget)
+ {
if (@interface == null) throw new
ArgumentNullException("interface");
Debug.Assert(@interface.IsInterface,
"@interface.IsInterface", "Should be adding mapping only...");
- Debug.Assert(@interface.IsAssignableFrom(targetType),
"@interface.IsAssignableFrom(targetType)",
- "Shouldn't be adding mapping
to interface that target does not implement...");
this.namingScope = namingScope;
-
- this.mapping = targetType.GetInterfaceMap(@interface);
-
+ this.canChangeTarget = canChangeTarget;
mixinInterface = @interface;
}
@@ -48,7 +47,7 @@
Debug.Assert(hook != null, "hook != null");
// TODO: once tokens for method on target are obtained
dynamically
// this should be changed to InterfaceMembersCollector
- var item = new
InterfaceMembersOnClassCollector(mixinInterface, this, false, mapping);
+ var item = new
InterfaceMembersCollector(mixinInterface);
item.CollectMembersToProxy(hook);
target = item;
@@ -120,7 +119,7 @@
var invocation = new
InvocationTypeGenerator(method.Method.DeclaringType,
method,
method.Method,
-
CanChangeTarget)
+
canChangeTarget)
.Generate(emitter, options,
namingScope);
var interceptors =
emitter.GetField("__interceptors");
@@ -129,7 +128,7 @@
invocation,
interceptors,
createMethod,
- (c, i)
=> field.ToExpression());
+
getTargetExpression);
}
else
{
@@ -143,5 +142,10 @@
proxyMethod.DefineCustomAttribute(attribute);
}
}
+
+ public void SetGetTargetExpression(GetTargetExpressionDelegate
getTarget)
+ {
+ getTargetExpression = getTarget;
+ }
}
}
File [modified]: MixinContributor.cs
Delta lines: +5 -1
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/MixinContributorBase.cs
2009-11-12 20:58:14 UTC (rev 6319)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/MixinContributorBase.cs
2009-11-13 16:21:11 UTC (rev 6320)
@@ -25,9 +25,13 @@
protected FieldReference field;
protected Type mixinInterface;
+ protected GetTargetExpressionDelegate getTargetExpression;
+ protected MixinContributorBase()
+ {
+ getTargetExpression = (c, i) =>
BackingField.ToExpression();
+ }
-
public FieldReference BackingField
{
File [modified]: MixinContributorBase.cs
Delta lines: +2 -2
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/ClassProxyGenerator.cs
2009-11-12 20:58:14 UTC (rev 6319)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/ClassProxyGenerator.cs
2009-11-13 16:21:11 UTC (rev 6320)
@@ -181,14 +181,14 @@
{
if
(!typeImplementerMapping.ContainsKey(mixinInterface))
{
- var mixin = new
MixinContributor(mixinInstance.GetType(), mixinInterface, namingScope);
+ var mixin = new
MixinContributor(mixinInterface, namingScope);
mixins.Add(mixin);
SafeAddMapping(mixinInterface, mixin, typeImplementerMapping);
}
}
}
}
- var additionalInterfacesContributor = new
InterfaceProxyWithoutTargetContributor(namingScope);
+ var additionalInterfacesContributor = new
InterfaceProxyWithoutTargetContributor(namingScope, (c, m) =>
NullExpression.Instance);
// 3. then additional interfaces
foreach (var @interface in additionalInterfaces)
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/
==================================================================
File [modified]: ClassProxyGenerator.cs
Delta lines: +8 -8
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/Emitters/SimpleAST/NullCoalescingOperatorExpression.cs
2009-11-12 20:58:14 UTC (rev 6319)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/Emitters/SimpleAST/NullCoalescingOperatorExpression.cs
2009-11-13 16:21:11 UTC (rev 6320)
@@ -19,14 +19,14 @@
public class NullCoalescingOperatorExpression:Expression
{
- private readonly Reference reference;
- private readonly Reference @default;
+ private readonly Expression expression;
+ private readonly Expression @default;
- public NullCoalescingOperatorExpression(Reference reference,
Reference @default)
+ public NullCoalescingOperatorExpression(Expression expression,
Expression @default)
{
- if (reference == null)
+ if (expression == null)
{
- throw new ArgumentNullException("reference");
+ throw new ArgumentNullException("expression");
}
if (@default == null)
@@ -34,18 +34,18 @@
throw new ArgumentNullException("default");
}
- this.reference = reference;
+ this.expression = expression;
th...@default = @default;
}
public override void Emit(IMemberEmitter member, ILGenerator
gen)
{
- reference.LoadReference(gen);
+ expression.Emit(member, gen);
gen.Emit(OpCodes.Dup);
var label = gen.DefineLabel();
gen.Emit(OpCodes.Brtrue_S, label);
gen.Emit(OpCodes.Pop);
- @default.LoadReference(gen);
+ @default.Emit(member, gen);
gen.MarkLabel(label);
}
File [modified]: InterfaceProxyWithTargetGenerator.cs
Delta lines: +14 -1
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InterfaceProxyWithTargetInterfaceGenerator.cs
2009-11-12 20:58:14 UTC (rev 6319)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InterfaceProxyWithTargetInterfaceGenerator.cs
2009-11-13 16:21:11 UTC (rev 6320)
@@ -17,6 +17,7 @@
using System;
using System.Collections.Generic;
+ using Castle.DynamicProxy.Generators.Emitters.SimpleAST;
using Castle.DynamicProxy.Serialization;
using Contributors;
@@ -35,9 +36,21 @@
return contributor;
}
+ protected override MixinContributor
GetContributorForMixin(INamingScope namingScope, Type mixinInterface, object
mixinInstance)
+ {
+ var contributorForMixin = new
MixinContributor(mixinInterface, namingScope,true);
+ contributorForMixin.SetGetTargetExpression(
+ (c, m) => new NullCoalescingOperatorExpression(
+ new
AsTypeReference(c.GetField("__target"), mixinInterface).ToExpression(),
+
contributorForMixin.BackingField.ToExpression()));
+ return contributorForMixin;
+ }
+
protected override InterfaceProxyWithoutTargetContributor
GetContributorForAdditionalInterfaces(INamingScope namingScope)
{
- return new
InterfaceProxyWithTargetInterfaceContributor(namingScope);
+ return new InterfaceProxyWithoutTargetContributor(
+ namingScope,
+ (@class, method) => new
AsTypeReference(@class.GetField("__target"),
method.DeclaringType).ToExpression());
}
File [modified]: InterfaceProxyWithTargetInterfaceGenerator.cs
Delta lines: +1 -1
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InterfaceProxyWithoutTargetGenerator.cs
2009-11-12 20:58:14 UTC (rev 6319)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InterfaceProxyWithoutTargetGenerator.cs
2009-11-13 16:21:11 UTC (rev 6320)
@@ -30,7 +30,7 @@
protected override ITypeContributor
AddMappingForTargetType(IDictionary<Type, ITypeContributor>
interfaceTypeImplementerMapping, Type proxyTargetType, ICollection<Type>
targetInterfaces, ICollection<Type> additionalInterfaces, INamingScope
namingScope)
{
- var contributor = new
InterfaceProxyWithoutTargetContributor(namingScope);
+ var contributor = new
InterfaceProxyWithoutTargetContributor(namingScope, (c, m) =>
NullExpression.Instance);
foreach (var @interface in
TypeUtil.GetAllInterfaces(targetType))
{
File [modified]: InterfaceProxyWithoutTargetGenerator.cs
Delta lines: +57 -0
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/ProxyGenerator.cs
2009-11-12 20:58:14 UTC (rev 6319)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/ProxyGenerator.cs
2009-11-13 16:21:11 UTC (rev 6320)
@@ -319,6 +319,63 @@
}
/// <summary>
+ /// Creates proxy object intercepting calls to members of
interface <typeparamref name="TInterface"/> on <paramref name="target"/> object
with given <paramref name="interceptors"/>.
+ /// Interceptors can use <see cref="IChangeProxyTarget"/>
interface to provide other target for method invocation than default <paramref
name="target"/>.
+ /// </summary>
+ /// <typeparam name="TInterface">Type of the interface
implemented by <paramref name="target"/> which will be proxied.</typeparam>
+ /// <param name="target">The target object, calls to which will
be intercepted.</param>
+ /// <param name="interceptors">The interceptors called during
the invocation of proxied methods.</param>
+ /// <returns>
+ /// Object proxying calls to members of <typeparamref
name="TInterface"/> type on <paramref name="target"/> object or alternative
implementation swapped at runtime by an interceptor.
+ /// </returns>
+ /// <exception cref="ArgumentNullException">Thrown when given
<paramref name="target"/> object is a null reference (Nothing in Visual
Basic).</exception>
+ /// <exception cref="ArgumentNullException">Thrown when given
<paramref name="interceptors"/> array is a null reference (Nothing in Visual
Basic).</exception>
+ /// <exception cref="ArgumentException">Thrown when given
<typeparamref name="TInterface"/> is not an interface type.</exception>
+ /// <exception cref="MissingMethodException">Thrown when no
default constructor exists on actual type of <paramref name="target"/>
object.</exception>
+ /// <exception cref="TargetInvocationException">Thrown when
default constructor of actual type of <paramref name="target"/> throws an
exception.</exception>
+ /// <remarks>
+ /// This method uses <see cref="IProxyBuilder"/> implementation
to generate a proxy type.
+ /// As such caller should expect any type of exception that
given <see cref="IProxyBuilder"/> implementation may throw.
+ /// </remarks>
+ public TInterface
CreateInterfaceProxyWithTargetInterface<TInterface>(TInterface target,
+
params IInterceptor[] interceptors)
where TInterface : class
+ {
+ return
(TInterface)CreateInterfaceProxyWithTargetInterface(typeof(TInterface),
+
target,
+
ProxyGenerationOptions.Default,
+
interceptors);
+ }
+
+ /// <summary>
+ /// Creates proxy object intercepting calls to members of
interface <typeparamref name="TInterface"/> on <paramref name="target"/> object
with given <paramref name="interceptors"/>.
+ /// Interceptors can use <see cref="IChangeProxyTarget"/>
interface to provide other target for method invocation than default <paramref
name="target"/>.
+ /// </summary>
+ /// <typeparam name="TInterface">Type of the interface
implemented by <paramref name="target"/> which will be proxied.</typeparam>
+ /// <param name="target">The target object, calls to which will
be intercepted.</param>
+ /// <param name="options">The proxy generation options used to
influence generated proxy type and object.</param>
+ /// <param name="interceptors">The interceptors called during
the invocation of proxied methods.</param>
+ /// <returns>
+ /// Object proxying calls to members of <typeparamref
name="TInterface"/> type on <paramref name="target"/> object or alternative
implementation swapped at runtime by an interceptor.
+ /// </returns>
+ /// <exception cref="ArgumentNullException">Thrown when given
<paramref name="target"/> object is a null reference (Nothing in Visual
Basic).</exception>
+ /// <exception cref="ArgumentNullException">Thrown when given
<paramref name="interceptors"/> array is a null reference (Nothing in Visual
Basic).</exception>
+ /// <exception cref="ArgumentException">Thrown when given
<typeparamref name="TInterface"/> is not an interface type.</exception>
+ /// <exception cref="MissingMethodException">Thrown when no
default constructor exists on actual type of <paramref name="target"/>
object.</exception>
+ /// <exception cref="TargetInvocationException">Thrown when
default constructor of actual type of <paramref name="target"/> throws an
exception.</exception>
+ /// <remarks>
+ /// This method uses <see cref="IProxyBuilder"/> implementation
to generate a proxy type.
+ /// As such caller should expect any type of exception that
given <see cref="IProxyBuilder"/> implementation may throw.
+ /// </remarks>
+ public TInterface
CreateInterfaceProxyWithTargetInterface<TInterface>(TInterface target,
ProxyGenerationOptions options,
+
params IInterceptor[] interceptors)
where TInterface : class
+ {
+ return
(TInterface)CreateInterfaceProxyWithTargetInterface(typeof(TInterface),
+
target,
+
options,
+
interceptors);
+ }
+
+ /// <summary>
/// Creates proxy object intercepting calls to members of
interface <paramref name="interfaceToProxy"/> on <paramref name="target"/>
object with given <paramref name="interceptors"/>.
/// Interceptors can use <see cref="IChangeProxyTarget"/>
interface to provide other target for method invocation than default <paramref
name="target"/>.
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Interfaces/
========================================================================
File [modified]: Two.cs
Delta lines: +0 -0
===================================================================
Directory:
/DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/Emitters/SimpleAST/
=====================================================================================
File [modified]: NullCoalescingOperatorExpression.cs
Delta lines: +7 -2
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InterfaceProxyWithTargetGenerator.cs
2009-11-12 20:58:14 UTC (rev 6319)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InterfaceProxyWithTargetGenerator.cs
2009-11-13 16:21:11 UTC (rev 6320)
@@ -247,7 +247,7 @@
{
if
(!typeImplementerMapping.ContainsKey(mixinInterface))
{
- var mixin = new
MixinContributor(mixinInstance.GetType(), mixinInterface, namingScope);
+ var mixin =
GetContributorForMixin(namingScope, mixinInterface, mixinInstance);
mixins.Add(mixin);
typeImplementerMapping.Add(mixinInterface, mixin);
}
@@ -291,9 +291,14 @@
return typeImplementerMapping;
}
+ protected virtual MixinContributor
GetContributorForMixin(INamingScope namingScope, Type mixinInterface, object
mixinInstance)
+ {
+ return new MixinContributor(mixinInterface,
namingScope);
+ }
+
protected virtual InterfaceProxyWithoutTargetContributor
GetContributorForAdditionalInterfaces(INamingScope namingScope)
{
- return new
InterfaceProxyWithoutTargetContributor(namingScope);
+ return new
InterfaceProxyWithoutTargetContributor(namingScope, (c, m) =>
NullExpression.Instance);
}
--
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=.