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
.Reflection
;
19 using Castle
.Core
.Interceptor
;
20 using Castle
.DynamicProxy
.Generators
;
21 using Castle
.DynamicProxy
.Tests
.BugsReported
;
22 using Castle
.DynamicProxy
.Tests
.Classes
;
23 using Castle
.DynamicProxy
.Tests
.Interceptors
;
24 using Castle
.DynamicProxy
.Tests
.InterClasses
;
25 using NUnit
.Framework
;
26 using ClassWithIndexer
=Castle
.DynamicProxy
.Tests
.Classes
.ClassWithIndexer
;
29 public class BasicClassProxyTestCase
: BasePEVerifyTestCase
31 private ProxyGenerator generator
;
36 generator
= new ProxyGenerator();
40 public void ProxyForClass()
42 object proxy
= generator
.CreateClassProxy(
43 typeof(ServiceClass
), new ResultModifierInterceptor());
45 Assert
.IsNotNull(proxy
);
46 Assert
.IsTrue(typeof(ServiceClass
).IsAssignableFrom(proxy
.GetType()));
48 ServiceClass instance
= (ServiceClass
) proxy
;
50 // return value is changed by the interceptor
51 Assert
.AreEqual(44, instance
.Sum(20, 25));
53 // return value is changed by the interceptor
54 Assert
.AreEqual(true, instance
.Valid
);
56 // The rest aren't changed
57 Assert
.AreEqual(45, instance
.Sum((byte)20, (byte)25)); // byte
58 Assert
.AreEqual(45, instance
.Sum(20L, 25L)); // long
59 Assert
.AreEqual(45, instance
.Sum((short)20, (short)25)); // short
60 Assert
.AreEqual(45, instance
.Sum(20f
, 25f
)); // float
61 Assert
.AreEqual(45, instance
.Sum(20.0, 25.0)); // double
62 Assert
.AreEqual(45, instance
.Sum((ushort)20, (ushort)25)); // ushort
63 Assert
.AreEqual(45, instance
.Sum((uint)20, (uint)25)); // uint
64 Assert
.AreEqual(45, instance
.Sum((ulong)20, (ulong)25)); // ulong
70 object proxy
= generator
.CreateClassProxy(
71 typeof(ServiceClass
), new StandardInterceptor());
72 proxy
= generator
.CreateClassProxy(
73 typeof(ServiceClass
), new StandardInterceptor());
74 proxy
= generator
.CreateClassProxy(
75 typeof(ServiceClass
), new StandardInterceptor());
76 proxy
= generator
.CreateClassProxy(
77 typeof(ServiceClass
), new StandardInterceptor());
80 [Test
, ExpectedException(typeof(GeneratorException
), "Type is not public, so a proxy " +
81 "cannot be generated. Type: System.AppDomainInitializerInfo")]
82 public void ProxyForNonPublicClass()
84 //have to use a type that is not from this assembly, because it is marked as internals visible to
87 object proxy
= generator
.CreateClassProxy(
88 Type
.GetType("System.AppDomainInitializerInfo, mscorlib"), new StandardInterceptor());
92 public void ProxyForClassWithIndexer()
94 LogInvocationInterceptor logger
= new LogInvocationInterceptor();
96 object proxy
= generator
.CreateClassProxy(typeof(ClassWithIndexer
), logger
);
98 Assert
.IsNotNull(proxy
);
99 Assert
.IsInstanceOfType(typeof(ClassWithIndexer
), proxy
);
101 ClassWithIndexer type
= (ClassWithIndexer
) proxy
;
104 Assert
.AreEqual(10, type
["name"]);
106 Assert
.AreEqual("set_Item get_Item ", logger
.LogContents
);
110 public void ClassWithDifferentAccessLevelOnProperties()
112 LogInvocationInterceptor logger
= new LogInvocationInterceptor();
114 object proxy
= generator
.CreateClassProxy(typeof(DiffAccessLevelOnProperties
), logger
);
116 Assert
.IsNotNull(proxy
);
117 Assert
.IsInstanceOfType(typeof(DiffAccessLevelOnProperties
), proxy
);
119 DiffAccessLevelOnProperties type
= (DiffAccessLevelOnProperties
) proxy
;
121 type
.SetProperties();
123 Assert
.AreEqual("10 11 12 13 name", type
.ToString());
127 public void ClassWithInheritance()
129 LogInvocationInterceptor logger
= new LogInvocationInterceptor();
131 object proxy
= generator
.CreateClassProxy(typeof(ExtendedServiceClass
), logger
);
133 Assert
.IsNotNull(proxy
);
135 ExtendedServiceClass extended
= (ExtendedServiceClass
) proxy
;
140 Assert
.AreEqual("Sum2 Sum ", logger
.LogContents
);
144 public void ProxyForNestedClass()
146 object proxy
= generator
.CreateClassProxy(typeof(ServiceClass
.InernalClass
), new Type
[] { typeof(IDisposable) }
);
147 Assert
.IsNotNull(proxy
);
148 Assert
.IsTrue(proxy
is ServiceClass
.InernalClass
);
152 public void ProxyForClassWithInterfaces()
154 object proxy
= generator
.CreateClassProxy(typeof(ServiceClass
), new Type
[] { typeof(IDisposable) }
,
155 new ResultModifierInterceptor());
157 Assert
.IsNotNull(proxy
);
158 Assert
.IsTrue(typeof(ServiceClass
).IsAssignableFrom(proxy
.GetType()));
159 Assert
.IsTrue(typeof(IDisposable
).IsAssignableFrom(proxy
.GetType()));
161 ServiceClass inter
= (ServiceClass
)proxy
;
163 Assert
.AreEqual(44, inter
.Sum(20, 25));
164 Assert
.AreEqual(true, inter
.Valid
);
168 IDisposable disp
= (IDisposable
) proxy
;
171 Assert
.Fail("Expected exception as Dispose has no implementation");
173 catch(NotImplementedException ex
)
175 Assert
.AreEqual("This is a DynamicProxy2 error: the interceptor attempted " +
176 "to 'Proceed' for a method without a target, for example, an interface method", ex
.Message
);
181 public void ProxyForCharReturnType()
183 LogInvocationInterceptor logger
= new LogInvocationInterceptor();
184 object proxy
= generator
.CreateClassProxy(typeof(ClassWithCharRetType
), logger
);
185 Assert
.IsNotNull(proxy
);
186 ClassWithCharRetType classProxy
= (ClassWithCharRetType
) proxy
;
187 Assert
.AreEqual('c', classProxy
.DoSomething());
191 public void ProxyForClassWithConstructors()
193 object proxy
= generator
.CreateClassProxy(
194 typeof(ClassWithConstructors
), new IInterceptor
[] { new StandardInterceptor() }
,
195 new object[] { "name" }
);
197 Assert
.IsNotNull(proxy
);
198 ClassWithConstructors classProxy
= (ClassWithConstructors
) proxy
;
199 Assert
.AreEqual("name", classProxy
.Name
);
201 proxy
= generator
.CreateClassProxy(
202 typeof(ClassWithConstructors
), new IInterceptor
[] { new StandardInterceptor() }
,
203 new object[] { "name", 10 }
);
205 Assert
.IsNotNull(proxy
);
206 classProxy
= (ClassWithConstructors
) proxy
;
207 Assert
.AreEqual("name", classProxy
.Name
);
208 Assert
.AreEqual(10, classProxy
.X
);
212 /// See http://support.castleproject.org/browse/DYNPROXY-43
215 public void MethodParamNamesAreReplicated()
217 MyClass mc
= generator
.CreateClassProxy
<MyClass
>(new StandardInterceptor());
218 ParameterInfo
[] methodParams
= GetMyTestMethodParams(mc
.GetType());
219 Assert
.AreEqual("myParam", methodParams
[0].Name
);
223 public void ProducesInvocationsThatCantChangeTarget()
225 AssertCannotChangeTargetInterceptor invocationChecker
= new AssertCannotChangeTargetInterceptor();
226 object proxy
= generator
.CreateClassProxy(typeof(ClassWithCharRetType
), invocationChecker
);
227 Assert
.IsNotNull(proxy
);
228 ClassWithCharRetType classProxy
= (ClassWithCharRetType
) proxy
;
229 Assert
.AreEqual('c', classProxy
.DoSomething());
233 [Ignore("Multi dimensional arrays seems to not work at all")]
234 public void ProxyTypeWithMultiDimentionalArrayAsParameters()
236 LogInvocationInterceptor log
= new LogInvocationInterceptor();
238 ClassWithMultiDimentionalArray proxy
=
239 generator
.CreateClassProxy
<ClassWithMultiDimentionalArray
>(log
);
241 int[,] x
= new int[1, 2];
243 proxy
.Do(new int[] { 1 }
);
245 proxy
.Do3(new string[] {"1", "2"}
);
247 Assert
.AreEqual("Do Do2 Do3 ", log
.LogContents
);
250 private ParameterInfo
[] GetMyTestMethodParams(Type type
)
252 MethodInfo methodInfo
= type
.GetMethod("MyTestMethod");
253 return methodInfo
.GetParameters();