1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle
.DynamicProxy
.Tests
18 using System
.Collections
;
19 using System
.Reflection
;
20 using Castle
.DynamicProxy
.Generators
;
21 using Castle
.DynamicProxy
.Tests
.GenInterfaces
;
22 using Castle
.DynamicProxy
.Tests
.Interceptors
;
23 using NUnit
.Framework
;
26 public class GenericInterfaceProxyTestCase
: BasePEVerifyTestCase
28 private LogInvocationInterceptor logger
;
30 public override void Init()
33 logger
= new LogInvocationInterceptor();
37 public void ProxyWithGenericArgument()
39 GenInterface
<int> proxy
=
40 generator
.CreateInterfaceProxyWithTarget
<GenInterface
<int>>(
41 new GenInterfaceImpl
<int>(), logger
);
43 Assert
.IsNotNull(proxy
);
45 Assert
.AreEqual(1, proxy
.DoSomething(1));
47 Assert
.AreEqual("DoSomething ", logger
.LogContents
);
53 public void ProxyWithGenericArgumentAndGenericMethod()
55 GenInterfaceWithGenMethods
<int> proxy
=
56 generator
.CreateInterfaceProxyWithTarget
<GenInterfaceWithGenMethods
<int>>(
57 new GenInterfaceWithGenMethodsImpl
<int>(), logger
);
59 Assert
.IsNotNull(proxy
);
61 proxy
.DoSomething
<long>(10L, 1);
63 Assert
.AreEqual("DoSomething ", logger
.LogContents
);
67 public void ProxyWithGenericArgumentAndGenericMethodAndGenericReturn()
69 GenInterfaceWithGenMethodsAndGenReturn
<int> proxy
=
70 generator
.CreateInterfaceProxyWithTarget
<GenInterfaceWithGenMethodsAndGenReturn
<int>>(
71 new GenInterfaceWithGenMethodsAndGenReturnImpl
<int>(), logger
);
73 Assert
.IsNotNull(proxy
);
75 Assert
.AreEqual(10L, proxy
.DoSomething
<long>(10L, 1));
77 Assert
.AreEqual("DoSomething ", logger
.LogContents
);
81 public void ProxyWithGenInterfaceWithGenericArrays()
83 IGenInterfaceWithGenArray
<int> proxy
=
84 generator
.CreateInterfaceProxyWithTarget
<IGenInterfaceWithGenArray
<int>>(
85 new GenInterfaceWithGenArray
<int>(), logger
);
87 Assert
.IsNotNull(proxy
);
89 int[] items
= new int[] {1, 2, 3}
;
91 items
= proxy
.CreateItems();
92 Assert
.IsNotNull(items
);
93 Assert
.AreEqual(3, items
.Length
);
95 Assert
.AreEqual("CopyTo CreateItems ", logger
.LogContents
);
99 public void ProxyWithGenInterfaceWithBase()
101 IGenInterfaceHierarchySpecialization
<int> proxy
=
102 generator
.CreateInterfaceProxyWithTarget
<IGenInterfaceHierarchySpecialization
<int>>(
103 new GenInterfaceHierarchy
<int>(), logger
);
105 Assert
.IsNotNull(proxy
);
109 Assert
.IsNotNull(proxy
.FetchAll());
111 Assert
.AreEqual("Add Add FetchAll ", logger
.LogContents
);
115 [ExpectedException(typeof(GeneratorException
),
116 "DynamicProxy cannot create an interface (with target) proxy for 'InterfaceWithExplicitImpl`1' as the target 'GenExplicitImplementation`1' has an explicit implementation of one of the methods exposed by the interface. The runtime prevents use from invoking the private method on the target. Method Castle.DynamicProxy.Tests.GenInterfaces.InterfaceWithExplicitImpl<T>.GetEnum1"
118 public void ProxyWithGenExplicitImplementation()
120 DisableVerification();
121 generator
.CreateInterfaceProxyWithTarget
<InterfaceWithExplicitImpl
<int>> (
122 new GenExplicitImplementation
<int>(), logger
);
126 public void TwoGenericsInterfaceWithoutTarget()
128 generator
.CreateInterfaceProxyWithoutTarget(typeof(GenInterface
<object>),
129 new Type
[] {typeof(InterfaceWithExplicitImpl<int>)}
,
130 new LogInvocationInterceptor());
134 public void NonGenInterfaceWithParentGenClassImplementingGenInterface()
136 generator
.CreateInterfaceProxyWithoutTarget(typeof(IUserRepository
),
137 new Type
[] {typeof(InterfaceWithExplicitImpl<int>)}
,
138 new LogInvocationInterceptor());
142 public void WithoutTarget()
144 generator
.CreateInterfaceProxyWithoutTarget(typeof(InterfaceWithExplicitImpl
<int>), new LogInvocationInterceptor());
148 public void MethodInfoClosedInGenIfcGenMethodRefTypeNoTarget()
150 KeepDataInterceptor interceptor
= new KeepDataInterceptor();
151 GenInterfaceWithGenMethods
<ArrayList
> proxy
=
152 generator
.CreateInterfaceProxyWithoutTarget
<GenInterfaceWithGenMethods
<ArrayList
>>(interceptor
);
154 proxy
.DoSomething(1, null);
155 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(void), typeof(int),
157 Assert
.AreEqual(interceptor
.Invocation
.GetConcreteMethod(),
158 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
160 proxy
.DoSomething(new Hashtable(), new ArrayList());
161 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(void),
162 typeof(Hashtable
), typeof(ArrayList
));
163 Assert
.AreEqual(interceptor
.Invocation
.GetConcreteMethod(),
164 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
168 public void MethodInfoClosedInGenIfcGenMethodValueTypeNoTarget()
170 KeepDataInterceptor interceptor
= new KeepDataInterceptor();
171 GenInterfaceWithGenMethods
<int> proxy
=
172 generator
.CreateInterfaceProxyWithoutTarget
<GenInterfaceWithGenMethods
<int>>(interceptor
);
174 proxy
.DoSomething(1, 1);
175 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(void), typeof(int),
177 Assert
.AreEqual(interceptor
.Invocation
.GetConcreteMethod(),
178 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
180 proxy
.DoSomething(new Hashtable(), 1);
181 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(void),
182 typeof(Hashtable
), typeof(int));
183 Assert
.AreEqual(interceptor
.Invocation
.GetConcreteMethod(),
184 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
188 public void MethodInfoClosedInGenIfcNongenMethodRefTypeNoTarget()
190 KeepDataInterceptor interceptor
= new KeepDataInterceptor();
191 IGenInterfaceHierarchyBase
<ArrayList
> proxy
=
192 generator
.CreateInterfaceProxyWithoutTarget
<IGenInterfaceHierarchyBase
<ArrayList
>>(interceptor
);
195 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(ArrayList
));
196 Assert
.AreEqual(interceptor
.Invocation
.GetConcreteMethod(),
197 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
200 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(void),
202 Assert
.AreEqual(interceptor
.Invocation
.GetConcreteMethod(),
203 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
207 public void MethodInfoClosedInGenIfcNongenMethodValueTypeNoTarget()
209 KeepDataInterceptor interceptor
= new KeepDataInterceptor();
210 IGenInterfaceHierarchyBase
<int> proxy
=
211 generator
.CreateInterfaceProxyWithoutTarget
<IGenInterfaceHierarchyBase
<int>>(interceptor
);
214 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(int));
215 Assert
.AreEqual(interceptor
.Invocation
.GetConcreteMethod(),
216 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
219 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(void), typeof(int));
220 Assert
.AreEqual(interceptor
.Invocation
.GetConcreteMethod(),
221 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
225 public void MethodInfoClosedInNongenIfcGenMethodNoTarget()
227 KeepDataInterceptor interceptor
= new KeepDataInterceptor();
228 OnlyGenMethodsInterface proxy
= generator
.CreateInterfaceProxyWithoutTarget
<OnlyGenMethodsInterface
>(interceptor
);
230 proxy
.DoSomething(1);
231 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(int), typeof(int));
232 Assert
.AreEqual(interceptor
.Invocation
.GetConcreteMethod(),
233 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
235 proxy
.DoSomething(new Hashtable());
236 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(Hashtable
),
238 Assert
.AreEqual(interceptor
.Invocation
.GetConcreteMethod(),
239 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
243 public void MethodInfoClosedInGenIfcGenMethodRefTypeWithTarget()
245 KeepDataInterceptor interceptor
= new KeepDataInterceptor();
246 GenInterfaceWithGenMethods
<ArrayList
> target
= new GenInterfaceWithGenMethodsImpl
<ArrayList
>();
247 GenInterfaceWithGenMethods
<ArrayList
> proxy
=
248 generator
.CreateInterfaceProxyWithTarget
<GenInterfaceWithGenMethods
<ArrayList
>>(target
, interceptor
);
250 proxy
.DoSomething(1, null);
251 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(void), typeof(int),
253 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethodInvocationTarget(), typeof(void),
254 typeof(int), typeof(ArrayList
));
255 Assert
.AreNotEqual(interceptor
.Invocation
.GetConcreteMethod(),
256 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
258 proxy
.DoSomething(new Hashtable(), new ArrayList());
259 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(void),
260 typeof(Hashtable
), typeof(ArrayList
));
261 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethodInvocationTarget(), typeof(void),
262 typeof(Hashtable
), typeof(ArrayList
));
263 Assert
.AreNotEqual(interceptor
.Invocation
.GetConcreteMethod(),
264 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
268 public void MethodInfoClosedInGenIfcGenMethodValueTypeWithTarget()
270 KeepDataInterceptor interceptor
= new KeepDataInterceptor();
271 GenInterfaceWithGenMethods
<int> target
= new GenInterfaceWithGenMethodsImpl
<int>();
272 GenInterfaceWithGenMethods
<int> proxy
=
273 generator
.CreateInterfaceProxyWithTarget
<GenInterfaceWithGenMethods
<int>>(target
, interceptor
);
275 proxy
.DoSomething(1, 1);
276 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(void), typeof(int),
278 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethodInvocationTarget(), typeof(void),
279 typeof(int), typeof(int));
280 Assert
.AreNotEqual(interceptor
.Invocation
.GetConcreteMethod(),
281 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
283 proxy
.DoSomething(new Hashtable(), 1);
284 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(void),
285 typeof(Hashtable
), typeof(int));
286 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethodInvocationTarget(), typeof(void),
287 typeof(Hashtable
), typeof(int));
288 Assert
.AreNotEqual(interceptor
.Invocation
.GetConcreteMethod(),
289 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
293 public void MethodInfoClosedInGenIfcNongenMethodRefTypeWithTarget()
295 KeepDataInterceptor interceptor
= new KeepDataInterceptor();
296 IGenInterfaceHierarchyBase
<ArrayList
> target
= new GenInterfaceHierarchy
<ArrayList
>();
297 IGenInterfaceHierarchyBase
<ArrayList
> proxy
=
298 generator
.CreateInterfaceProxyWithTarget
<IGenInterfaceHierarchyBase
<ArrayList
>>(target
, interceptor
);
301 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(void),
303 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethodInvocationTarget(), typeof(void),
305 Assert
.AreNotEqual(interceptor
.Invocation
.GetConcreteMethod(),
306 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
309 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(ArrayList
));
310 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethodInvocationTarget(),
312 Assert
.AreNotEqual(interceptor
.Invocation
.GetConcreteMethod(),
313 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
317 public void MethodInfoClosedInGenIfcNongenMethodValueTypeWithTarget()
319 KeepDataInterceptor interceptor
= new KeepDataInterceptor();
320 IGenInterfaceHierarchyBase
<int> target
= new GenInterfaceHierarchy
<int>();
321 IGenInterfaceHierarchyBase
<int> proxy
=
322 generator
.CreateInterfaceProxyWithTarget
<IGenInterfaceHierarchyBase
<int>>(target
, interceptor
);
325 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(void), typeof(int));
326 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethodInvocationTarget(), typeof(void),
328 Assert
.AreNotEqual(interceptor
.Invocation
.GetConcreteMethod(),
329 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
332 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(int));
333 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethodInvocationTarget(), typeof(int));
334 Assert
.AreNotEqual(interceptor
.Invocation
.GetConcreteMethod(),
335 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
339 public void MethodInfoClosedInNongenIfcGenMethodWithTarget()
341 KeepDataInterceptor interceptor
= new KeepDataInterceptor();
342 OnlyGenMethodsInterface target
= new OnlyGenMethodsInterfaceImpl();
343 OnlyGenMethodsInterface proxy
=
344 generator
.CreateInterfaceProxyWithTarget
<OnlyGenMethodsInterface
>(target
, interceptor
);
346 proxy
.DoSomething(1);
347 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(int), typeof(int));
348 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethodInvocationTarget(), typeof(int),
350 Assert
.AreNotEqual(interceptor
.Invocation
.GetConcreteMethod(),
351 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
353 proxy
.DoSomething(new Hashtable());
354 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethod(), typeof(Hashtable
),
356 GenericTestUtility
.CheckMethodInfoIsClosed(interceptor
.Invocation
.GetConcreteMethodInvocationTarget(),
357 typeof(Hashtable
), typeof(Hashtable
));
358 Assert
.AreNotEqual(interceptor
.Invocation
.GetConcreteMethod(),
359 interceptor
.Invocation
.GetConcreteMethodInvocationTarget());
363 [ExpectedException(typeof(ArgumentException
))]
364 public void ThrowsWhenProxyingGenericTypeDefNoTarget()
366 KeepDataInterceptor interceptor
= new KeepDataInterceptor();
367 object o
= generator
.CreateInterfaceProxyWithoutTarget(typeof(IGenInterfaceHierarchyBase
<>), interceptor
);
370 [Test(Description
= "There is a strange CLR bug resulting from our loading the tokens of methods in generic types. "
371 + "This test ensures we do not trigger it.")]
372 [Ignore("Currently, we trigger the bug, and work around it - see MethodFinder")]
373 public void TypeGetMethodsIsStable()
375 ProxyWithGenInterfaceWithBase();
376 Assert
.AreEqual(4, typeof(IGenInterfaceHierarchyBase
<int>).GetMethods().Length
);
379 [Test(Description
= "There is a strange CLR bug resulting from our loading the tokens of methods in generic types. "
380 + "This test ensures we correctly work around it.")]
381 public void MethodFinderIsStable()
383 ProxyWithGenInterfaceWithBase();
385 MethodFinder
.GetAllInstanceMethods(typeof(IGenInterfaceHierarchyBase
<int>),
386 BindingFlags
.Public
| BindingFlags
.Instance
).Length
);
389 [Test(Description
= "There is a strange CLR bug resulting from our loading the tokens of methods in generic types. "
391 "This test ensures we do not trigger it across AppDomains. If we do, MethodFinder must provide a cross-AppDomain workaround."
393 public void TypeGetMethodsIsStableInDifferentAppDomains()
395 ProxyWithGenInterfaceWithBase();
396 AppDomain newDomain
=
397 AppDomain
.CreateDomain("NewDomain", AppDomain
.CurrentDomain
.Evidence
, AppDomain
.CurrentDomain
.SetupInformation
);
400 newDomain
.DoCallBack(delegate { Assert.AreEqual(4, typeof(IGenInterfaceHierarchyBase<int>).GetMethods().Length); }
);
404 AppDomain
.Unload(newDomain
);