1 // Copyright 2004-2008 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
.Builder
.CodeGenerators
19 using System
.Reflection
;
20 using System
.Runtime
.Serialization
;
21 using System
.Threading
;
22 using Castle
.DynamicProxy
.Builder
.CodeBuilder
;
23 using Castle
.DynamicProxy
.Builder
.CodeBuilder
.SimpleAST
;
26 /// Summary description for InterfaceProxyGenerator.
29 public class InterfaceProxyGenerator
: BaseCodeGenerator
31 protected Type _targetType
;
32 protected FieldReference _targetField
;
34 public InterfaceProxyGenerator(ModuleScope scope
) : base(scope
)
38 public InterfaceProxyGenerator(ModuleScope scope
, GeneratorContext context
) : base(scope
, context
)
42 protected override Type InvocationType
44 get { return Context.InterfaceInvocation; }
47 protected override String
GenerateTypeName(Type type
, Type
[] interfaces
)
49 StringBuilder sb
= new StringBuilder();
50 foreach(Type inter
in interfaces
)
53 sb
.Append(GetTypeName(inter
));
56 String
.Format("ProxyInterface{2}{0}{1}", GetTypeName(type
), sb
.ToString(), NormalizeNamespaceName(type
.Namespace
));
59 protected override void GenerateFields()
61 base.GenerateFields();
62 _targetField
= MainTypeBuilder
.CreateField("__target", typeof(object));
66 protected override MethodInfo
GenerateCallbackMethodIfNecessary(MethodInfo method
, Reference invocationTarget
)
68 if (Context
.HasMixins
&& _interface2mixinIndex
.Contains(method
.DeclaringType
))
73 if (method
.IsAbstract
)
75 method
= GetCorrectMethod(method
);
78 return base.GenerateCallbackMethodIfNecessary(method
, _targetField
);
82 /// From an interface method (abstract) look up
83 /// for a matching method on the target
85 /// <param name="method"></param>
86 /// <returns></returns>
87 protected override MethodInfo
GetCorrectMethod(MethodInfo method
)
89 if (Context
.HasMixins
&& _interface2mixinIndex
.Contains(method
.DeclaringType
))
94 ParameterInfo
[] paramsInfo
= method
.GetParameters();
95 Type
[] argTypes
= new Type
[paramsInfo
.Length
];
97 for(int i
= 0; i
< argTypes
.Length
; i
++)
99 argTypes
[i
] = paramsInfo
[i
].ParameterType
;
102 MethodInfo newMethod
= _targetType
.GetMethod(method
.Name
, argTypes
);
104 if (newMethod
== null)
106 //System.Diagnostics.Trace.Write("Target class does not offer the method " + method.Name);
114 /// Generates one public constructor receiving
115 /// the <see cref="IInterceptor"/> instance and instantiating a HybridCollection
117 protected override EasyConstructor
GenerateConstructor()
119 ArgumentReference arg1
= new ArgumentReference(Context
.Interceptor
);
120 ArgumentReference arg2
= new ArgumentReference(typeof(object));
121 ArgumentReference arg3
= new ArgumentReference(typeof(object[]));
123 EasyConstructor constructor
;
125 if (Context
.HasMixins
)
127 constructor
= MainTypeBuilder
.CreateConstructor(arg1
, arg2
, arg3
);
131 constructor
= MainTypeBuilder
.CreateConstructor(arg1
, arg2
);
134 GenerateConstructorCode(constructor
.CodeBuilder
, arg1
, SelfReference
.Self
, arg3
);
136 constructor
.CodeBuilder
.InvokeBaseConstructor();
138 constructor
.CodeBuilder
.AddStatement(new AssignStatement(
139 _targetField
, arg2
.ToExpression()));
141 constructor
.CodeBuilder
.AddStatement(new ReturnStatement());
146 protected Type
[] Join(Type
[] interfaces
, Type
[] mixinInterfaces
)
148 Type
[] union
= new Type
[interfaces
.Length
+ mixinInterfaces
.Length
];
149 Array
.Copy(interfaces
, 0, union
, 0, interfaces
.Length
);
150 Array
.Copy(mixinInterfaces
, 0, union
, interfaces
.Length
, mixinInterfaces
.Length
);
154 protected override void CustomizeGetObjectData(AbstractCodeBuilder codebuilder
, ArgumentReference arg1
,
155 ArgumentReference arg2
)
157 Type
[] key_and_object
= new Type
[] {typeof(String), typeof(Object)}
;
158 MethodInfo addValueMethod
= typeof(SerializationInfo
).GetMethod("AddValue", key_and_object
);
160 codebuilder
.AddStatement(new ExpressionStatement(
161 new VirtualMethodInvocationExpression(arg1
, addValueMethod
,
162 new FixedReference("__target").ToExpression(),
163 _targetField
.ToExpression())));
166 protected override Expression
GetPseudoInvocationTarget(MethodInfo method
)
168 if (Context
.HasMixins
&& _interface2mixinIndex
.Contains(method
.DeclaringType
))
170 return base.GetPseudoInvocationTarget(method
);
173 return _targetField
.ToExpression();
176 protected override EasyProperty
CreateProperty(PropertyInfo property
)
178 //The Interceptor Property form the IProxy Interface -> Access the __interceptor Attribute
179 if ("Interceptor".Equals(property
.Name
) && typeof(IInterceptor
).Equals(property
.PropertyType
))
181 return CreateInterceptorProperty(property
);
183 return base.CreateProperty(property
);
186 private EasyProperty
CreateInterceptorProperty(PropertyInfo propertyInfo
)
188 EasyProperty interceptorProperty
= MainTypeBuilder
.CreateProperty(propertyInfo
);
189 EasyMethod getMethod
= interceptorProperty
.CreateGetMethod();
190 MethodInfo baseMethod
= typeof(MulticastDelegate
).GetMethod("get_Interceptor");
191 getMethod
.CodeBuilder
.AddStatement(new ReturnStatement(base.InterceptorField
));
192 return interceptorProperty
;
195 public virtual Type
GenerateCode(Type
[] interfaces
, Type targetType
)
197 if (Context
.HasMixins
)
199 _mixins
= Context
.MixinsAsArray();
200 Type
[] mixinInterfaces
= InspectAndRegisterInterfaces(_mixins
);
201 interfaces
= Join(interfaces
, mixinInterfaces
);
204 //interfaces = AddISerializable(interfaces);
205 interfaces
= AddInterfaces(new Type
[] {typeof(ISerializable), typeof(IProxy)}
, interfaces
);
207 ReaderWriterLock rwlock
= ModuleScope
.RWLock
;
209 rwlock
.AcquireReaderLock(-1);
211 Type cacheType
= GetFromCache(targetType
, interfaces
);
213 if (cacheType
!= null)
215 rwlock
.ReleaseReaderLock();
220 rwlock
.UpgradeToWriterLock(-1);
224 cacheType
= GetFromCache(targetType
, interfaces
);
226 if (cacheType
!= null)
231 _targetType
= targetType
;
233 CreateTypeBuilder(GenerateTypeName(targetType
, interfaces
), typeof(Object
), interfaces
);
235 ImplementGetObjectData(interfaces
);
236 ImplementCacheInvocationCache();
237 GenerateInterfaceImplementation(interfaces
);
238 GenerateConstructor();
244 rwlock
.ReleaseWriterLock();