Skip to content

Commit d8980c9

Browse files
committed
- Changed that all kind of interceptions do not intercept System.Object methods by default unless they are overridden.
- Added overloads to configure which methods are intercepted
1 parent 8ed2197 commit d8980c9

12 files changed

+354
-29
lines changed

src/Ninject.Extensions.Interception.Test/MethodInterceptionContext.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,8 @@ public void Equals_WhenUsingInterfaceProxy_IsInterceptable()
279279
{
280280
CountInterceptor.Reset();
281281

282-
kernel.Bind<IFoo>().To<NoneVirtualFooImplementation>().Intercept().With<CountInterceptor>();
282+
kernel.Bind<IFoo>().To<NoneVirtualFooImplementation>()
283+
.Intercept(mi => true).With<CountInterceptor>();
283284
var obj = kernel.Get<IFoo>();
284285
var result42 = obj.Equals(42);
285286
var result41 = obj.Equals(41);

src/Ninject.Extensions.Interception.Test/Ninject.Extensions.Interception.Tests.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@
148148
<Compile Include="Fakes\ViewModel.cs" />
149149
<Compile Include="PropertyInterceptionContextDynamicProxy2.cs" />
150150
<Compile Include="PropertyInterceptionContextLinFu.cs" />
151+
<Compile Include="SystemObjectMethodInterceptionContext.cs" />
152+
<Compile Include="SystemObjectMethodInterceptionContextDynamicProxy2.cs" />
153+
<Compile Include="SystemObjectMethodInterceptionContextLinFu.cs" />
151154
</ItemGroup>
152155
<ItemGroup>
153156
<ProjectReference Include="..\Ninject.Extensions.Interception.DynamicProxy\Ninject.Extensions.Interception.DynamicProxy.csproj">
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
using FluentAssertions;
2+
using Ninject.Extensions.Interception.Attributes;
3+
using Ninject.Extensions.Interception.Infrastructure.Language;
4+
using Ninject.Extensions.Interception.Request;
5+
using Xunit;
6+
7+
namespace Ninject.Extensions.Interception
8+
{
9+
public abstract class SystemObjectMethodInterceptionContext : InterceptionTestContext
10+
{
11+
public static bool InterceptionFlag = false;
12+
private readonly IKernel kernel;
13+
14+
protected SystemObjectMethodInterceptionContext()
15+
{
16+
InterceptionFlag = false;
17+
18+
kernel = base.CreateDefaultInterceptionKernel();
19+
}
20+
21+
[Fact]
22+
public void InterceptionUsingAttribute_InterceptsMethods()
23+
{
24+
kernel.Bind<IHaveInterceptAttribute>().To<HaveInterceptAttribute>();
25+
26+
kernel.Get<IHaveInterceptAttribute>().DoSomething();
27+
28+
InterceptionFlag.Should().BeTrue();
29+
}
30+
31+
[Fact]
32+
public void InterceptionUsingAttribute_DoesNotInterceptSystemObjectMethods()
33+
{
34+
kernel.Bind<IHaveInterceptAttribute>().To<HaveInterceptAttribute>();
35+
36+
kernel.Get<IHaveInterceptAttribute>().GetHashCode();
37+
38+
InterceptionFlag.Should().BeFalse();
39+
}
40+
41+
[Fact]
42+
public void InterceptionUsingAttribute_DoesInterceptOverridenSystemObjectMethods()
43+
{
44+
kernel.Bind<IHaveInterceptAttribute>().To<HaveInterceptAndOverrideGetHashCodeAttribute>();
45+
46+
kernel.Get<IHaveInterceptAttribute>().GetHashCode();
47+
48+
InterceptionFlag.Should().BeTrue();
49+
}
50+
51+
[Fact]
52+
public void InterceptionUsingBindingExtension_InterceptsMethods()
53+
{
54+
kernel.Bind<IHaveNoInterceptAttribute>().To<HaveNoInterceptAttribute>().Intercept().With<MethodInterceptor>();
55+
56+
kernel.Get<IHaveNoInterceptAttribute>().DoSomething();
57+
58+
InterceptionFlag.Should().BeTrue();
59+
}
60+
61+
[Fact]
62+
public void InterceptionUsingBindingExtension_DoesNotInterceptSystemObjectMethods()
63+
{
64+
kernel.Bind<IHaveNoInterceptAttribute>().To<HaveNoInterceptAttribute>().Intercept().With<MethodInterceptor>();
65+
66+
kernel.Get<IHaveNoInterceptAttribute>().GetHashCode();
67+
68+
InterceptionFlag.Should().BeFalse();
69+
}
70+
71+
[Fact]
72+
public void InterceptionUsingBindingExtension_DoesInterceptOverriddenSystemObjectMethods()
73+
{
74+
kernel.Bind<IHaveNoInterceptAttribute>().To<HaveNoInterceptAttributeButOverrideGetHashCode>().Intercept().With<MethodInterceptor>();
75+
76+
kernel.Get<IHaveNoInterceptAttribute>().GetHashCode();
77+
78+
InterceptionFlag.Should().BeTrue();
79+
}
80+
81+
[Fact]
82+
public void InterceptionUsingBindingExtension_WithInterceptAllMethodsPredicate_DoesInterceptSystemObjectMethods()
83+
{
84+
kernel.Bind<IHaveNoInterceptAttribute>().To<HaveNoInterceptAttribute>()
85+
.Intercept(mi => true).With<MethodInterceptor>();
86+
87+
kernel.Get<IHaveNoInterceptAttribute>().GetHashCode();
88+
89+
InterceptionFlag.Should().BeTrue();
90+
}
91+
92+
[Fact]
93+
public void InterceptionUsingBindingExtension_WithInterceptNothingPredicate_DoesNotInterceptMethods()
94+
{
95+
kernel.Bind<IHaveNoInterceptAttribute>().To<HaveNoInterceptAttribute>()
96+
.Intercept(mi => false).With<MethodInterceptor>();
97+
98+
kernel.Get<IHaveNoInterceptAttribute>().DoSomething();
99+
100+
InterceptionFlag.Should().BeFalse();
101+
}
102+
103+
[Fact]
104+
public void InterceptionUsingKernelExtension_InterceptsMethods()
105+
{
106+
kernel.Bind<IHaveNoInterceptAttribute>().To<HaveNoInterceptAttribute>();
107+
kernel
108+
.Intercept(ctx => typeof(IHaveNoInterceptAttribute).IsAssignableFrom(ctx.Plan.Type))
109+
.With<MethodInterceptor>();
110+
111+
kernel.Get<IHaveNoInterceptAttribute>().DoSomething();
112+
InterceptionFlag.Should().BeTrue();
113+
}
114+
115+
[Fact]
116+
public void InterceptionUsingKernelExtension_DoesNotInterceptSystemObjectMethods()
117+
{
118+
kernel.Bind<IHaveNoInterceptAttribute>().To<HaveNoInterceptAttribute>();
119+
kernel
120+
.Intercept(ctx => typeof(IHaveNoInterceptAttribute).IsAssignableFrom(ctx.Plan.Type))
121+
.With<MethodInterceptor>();
122+
123+
kernel.Get<IHaveNoInterceptAttribute>().GetHashCode();
124+
InterceptionFlag.Should().BeFalse();
125+
}
126+
127+
[Fact]
128+
public void InterceptionUsingKernelExtension_DoesInterceptOverriddenSystemObjectMethods()
129+
{
130+
kernel.Bind<IHaveNoInterceptAttribute>().To<HaveNoInterceptAttributeButOverrideGetHashCode>();
131+
kernel
132+
.Intercept(ctx => typeof(IHaveNoInterceptAttribute).IsAssignableFrom(ctx.Plan.Type))
133+
.With<MethodInterceptor>();
134+
135+
kernel.Get<IHaveNoInterceptAttribute>().GetHashCode();
136+
InterceptionFlag.Should().BeTrue();
137+
}
138+
139+
[Fact]
140+
public void InterceptionUsingKernelExtension_WithInterceptAllMethodsPredicate_DoesInterceptSystemObjectMethods()
141+
{
142+
kernel.Bind<IHaveNoInterceptAttribute>().To<HaveNoInterceptAttribute>();
143+
kernel
144+
.Intercept(
145+
ctx => typeof(IHaveNoInterceptAttribute).IsAssignableFrom(ctx.Plan.Type),
146+
mi => true
147+
)
148+
.With<MethodInterceptor>();
149+
150+
kernel.Get<IHaveNoInterceptAttribute>().GetHashCode();
151+
InterceptionFlag.Should().BeTrue();
152+
}
153+
154+
[Fact]
155+
public void InterceptionUsingKernelExtension_WithInterceptNothingPredicate_DoesNotInterceptMethods()
156+
{
157+
kernel.Bind<IHaveNoInterceptAttribute>().To<HaveNoInterceptAttribute>();
158+
kernel
159+
.Intercept(
160+
ctx => typeof(IHaveNoInterceptAttribute).IsAssignableFrom(ctx.Plan.Type),
161+
mi => false
162+
)
163+
.With<MethodInterceptor>();
164+
165+
kernel.Get<IHaveNoInterceptAttribute>().DoSomething();
166+
InterceptionFlag.Should().BeFalse();
167+
}
168+
169+
public interface IHaveInterceptAttribute
170+
{
171+
void DoSomething();
172+
}
173+
174+
[ChangeFlag]
175+
public class HaveInterceptAttribute : IHaveInterceptAttribute
176+
{
177+
public void DoSomething()
178+
{
179+
}
180+
}
181+
182+
public class HaveInterceptAndOverrideGetHashCodeAttribute : HaveInterceptAttribute
183+
{
184+
public override int GetHashCode()
185+
{
186+
return base.GetHashCode() + 1;
187+
}
188+
}
189+
190+
public interface IHaveNoInterceptAttribute
191+
{
192+
void DoSomething();
193+
}
194+
195+
public class HaveNoInterceptAttribute : IHaveNoInterceptAttribute
196+
{
197+
public virtual void DoSomething()
198+
{
199+
}
200+
}
201+
202+
public class HaveNoInterceptAttributeButOverrideGetHashCode : HaveNoInterceptAttribute
203+
{
204+
public override int GetHashCode()
205+
{
206+
return base.GetHashCode() + 1;
207+
}
208+
}
209+
210+
public class ChangeFlagAttribute : InterceptAttribute
211+
{
212+
public override IInterceptor CreateInterceptor(IProxyRequest request)
213+
{
214+
return new MethodInterceptor();
215+
}
216+
}
217+
218+
public class MethodInterceptor : IInterceptor
219+
{
220+
public void Intercept(IInvocation invocation)
221+
{
222+
InterceptionFlag = true;
223+
invocation.Proceed();
224+
}
225+
}
226+
}
227+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace Ninject.Extensions.Interception
2+
{
3+
public class SystemObjectMethodInterceptionContextDynamicProxy2 : SystemObjectMethodInterceptionContext
4+
{
5+
protected override InterceptionModule InterceptionModule
6+
{
7+
get { return new DynamicProxyModule(); }
8+
}
9+
}
10+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#if !SILVERLIGHT
2+
namespace Ninject.Extensions.Interception
3+
{
4+
public class SystemObjectMethodInterceptionContextLinFu : SystemObjectMethodInterceptionContext
5+
{
6+
protected override InterceptionModule InterceptionModule
7+
{
8+
get { return new LinFuModule(); }
9+
}
10+
}
11+
}
12+
#endif

src/Ninject.Extensions.Interception/Advice/Advice.cs

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#region Using Directives
1414

1515
using System;
16+
using System.Linq;
1617
using System.Reflection;
1718
using Ninject.Extensions.Interception.Infrastructure;
1819
using Ninject.Extensions.Interception.Infrastructure.Language;
@@ -52,6 +53,18 @@ public Advice(Predicate<IContext> condition)
5253
Condition = condition;
5354
}
5455

56+
/// <summary>
57+
/// Initializes a new instance of the <see cref="Advice"/> class.
58+
/// </summary>
59+
/// <param name="condition">The condition that will be evaluated for a request.</param>
60+
/// <param name="methodPredicate">The condition that will be evaluated to determine if the method call shall be intercepted.</param>
61+
public Advice(Predicate<IContext> condition, Predicate<MethodInfo> methodPredicate)
62+
{
63+
Ensure.ArgumentNotNull( condition, "condition" );
64+
Condition = condition;
65+
MethodPredicate = methodPredicate;
66+
}
67+
5568
#region IAdvice Members
5669

5770
/// <summary>
@@ -60,10 +73,16 @@ public Advice(Predicate<IContext> condition)
6073
public RuntimeMethodHandle MethodHandle { get; set; }
6174

6275
/// <summary>
63-
/// Gets or sets the condition for the advice, if it is dynamic.
76+
/// Gets or sets the condition for the advice that
77+
/// will be evaluated to determine if the method call shall be intercepted.
6478
/// </summary>
6579
public Predicate<IContext> Condition { get; set; }
6680

81+
/// <summary>
82+
/// Gets or sets the condition for the advice, if it is dynamic.
83+
/// </summary>
84+
public Predicate<MethodInfo> MethodPredicate { get; set; }
85+
6786
/// <summary>
6887
/// Gets or sets the interceptor associated with the advice, if applicable.
6988
/// </summary>
@@ -95,9 +114,41 @@ public bool IsDynamic
95114
/// <returns><see langword="True"/> if the request matches, otherwise <see langword="false"/>.</returns>
96115
public bool Matches( IProxyRequest request )
97116
{
98-
return IsDynamic ? Condition( request.Context ) : MatchesMethod(request);
117+
return IsDynamic
118+
? Condition(request.Context) && MatchesMethodPredicate(request)
119+
: MatchesMethod(request);
99120
}
100121

122+
/// <summary>
123+
/// Evaluates if the method predicate matches.
124+
/// </summary>
125+
/// <param name="request">The request.</param>
126+
/// <returns><c>true</c> if the predicate matches, <c>false</c> otherwise.</returns>
127+
private bool MatchesMethodPredicate(IProxyRequest request)
128+
{
129+
if (MethodPredicate == null)
130+
{
131+
return true;
132+
}
133+
134+
var requestMethod = request.Method;
135+
if (requestMethod.DeclaringType != request.Target.GetType())
136+
{
137+
requestMethod = request.Target.GetType()
138+
.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
139+
.SingleOrDefault(mi => mi.Name == requestMethod.Name &&
140+
mi.GetParameters().SequenceEqual(requestMethod.GetParameters()))
141+
?? requestMethod;
142+
}
143+
144+
return this.MethodPredicate(requestMethod);
145+
}
146+
147+
/// <summary>
148+
/// Evaluates if the method the method of this advice.
149+
/// </summary>
150+
/// <param name="request">The request.</param>
151+
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
101152
private bool MatchesMethod(IProxyRequest request)
102153
{
103154
if (request.Method.GetMethodHandle().Equals(this.MethodHandle))
@@ -107,10 +158,10 @@ private bool MatchesMethod(IProxyRequest request)
107158

108159
var requestType = request.Method.DeclaringType;
109160
if (requestType == null ||
110-
!requestType.IsInterface ||
161+
!requestType.IsInterface ||
111162
!requestType.IsAssignableFrom(this.method.DeclaringType))
112163
{
113-
return false;
164+
return this.method.GetBaseDefinition().GetMethodHandle() == request.Method.GetMethodHandle();
114165
}
115166

116167
var map = this.method.DeclaringType.GetInterfaceMap(request.Method.DeclaringType);

0 commit comments

Comments
 (0)