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
18 using System
.Collections
;
19 using System
.Collections
.Specialized
;
20 using System
.Reflection
;
21 using System
.Reflection
.Emit
;
22 using System
.Runtime
.Serialization
;
23 using System
.Threading
;
24 using Castle
.DynamicProxy
.Builder
.CodeBuilder
;
25 using Castle
.DynamicProxy
.Builder
.CodeBuilder
.SimpleAST
;
27 using System
.Runtime
.CompilerServices
;
31 /// Summary description for BaseCodeGenerator.
34 public abstract class BaseCodeGenerator
36 private ModuleScope _moduleScope
;
37 private GeneratorContext _context
;
39 private EasyType _typeBuilder
;
40 private FieldReference _interceptorField
;
41 private FieldReference _cacheField
;
42 private FieldReference _mixinField
;
43 private IList _generated
= new ArrayList();
45 private ReaderWriterLock internalsToDynProxyLock
= new ReaderWriterLock();
46 private System
.Collections
.Generic
.IDictionary
<Assembly
, bool> internalsToDynProxy
= new System
.Collections
.Generic
.Dictionary
<Assembly
, bool>();
48 protected Type _baseType
= typeof(Object
);
49 protected EasyMethod _method2Invocation
;
50 protected object[] _mixins
= new object[0];
53 /// Holds instance fields which points to delegates instantiated
55 protected ArrayList _cachedFields
= new ArrayList();
58 /// MethodInfo => Callable delegate
60 protected Hashtable _method2Delegate
= new Hashtable();
62 protected HybridDictionary _interface2mixinIndex
= new HybridDictionary();
64 protected BaseCodeGenerator(ModuleScope moduleScope
)
65 : this(moduleScope
, new GeneratorContext())
69 protected BaseCodeGenerator(ModuleScope moduleScope
, GeneratorContext context
)
71 _moduleScope
= moduleScope
;
75 protected ModuleScope ModuleScope
77 get { return _moduleScope; }
80 protected GeneratorContext Context
82 get { return _context; }
85 protected EasyType MainTypeBuilder
87 get { return _typeBuilder; }
90 protected FieldReference InterceptorField
92 get { return _interceptorField; }
95 protected FieldReference MixinField
97 get { return _mixinField; }
100 protected FieldReference CacheField
102 get { return _cacheField; }
105 protected abstract Type InvocationType { get; }
107 protected Type
GetFromCache(Type baseClass
, Type
[] interfaces
)
109 return ModuleScope
[GenerateTypeName(baseClass
, interfaces
)] as Type
;
112 protected void RegisterInCache(Type generatedType
)
114 ModuleScope
[generatedType
.FullName
] = generatedType
;
117 protected FieldReference
ObtainCallableFieldBuilderDelegate(EasyCallable builder
)
119 foreach(CallableField field
in _cachedFields
)
121 if (field
.Callable
== builder
)
130 protected void RegisterDelegateFieldToBeInitialized(
131 MethodInfo method
, FieldReference field
,
132 EasyCallable builder
, MethodInfo callbackMethod
)
134 int sourceArgIndex
= CallableField
.EmptyIndex
;
136 if (Context
.HasMixins
&& _interface2mixinIndex
.Contains(method
.DeclaringType
))
138 sourceArgIndex
= ((int) _interface2mixinIndex
[method
.DeclaringType
]);
141 _cachedFields
.Add(new CallableField(field
, builder
, callbackMethod
, sourceArgIndex
));
144 protected virtual EasyType
CreateTypeBuilder(String typeName
, Type baseType
, Type
[] interfaces
)
146 _baseType
= baseType
;
147 _typeBuilder
= new EasyType(ModuleScope
, typeName
, baseType
, interfaces
, true);
152 protected virtual void GenerateFields()
154 _interceptorField
= _typeBuilder
.CreateField("__interceptor", Context
.Interceptor
);
155 _cacheField
= _typeBuilder
.CreateField("__cache", typeof(HybridDictionary
), false);
156 _mixinField
= _typeBuilder
.CreateField("__mixin", typeof(object[]));
159 protected abstract String
GenerateTypeName(Type type
, Type
[] interfaces
);
161 protected virtual void ImplementGetObjectData(Type
[] interfaces
)
163 // To prevent re-implementation of this interface.
164 _generated
.Add(typeof(ISerializable
));
166 Type
[] get_type_args
= new Type
[] {typeof(String), typeof(bool), typeof(bool)}
;
167 Type
[] key_and_object
= new Type
[] {typeof(String), typeof(Object)}
;
168 MethodInfo addValueMethod
= typeof(SerializationInfo
).GetMethod("AddValue", key_and_object
);
170 ArgumentReference arg1
= new ArgumentReference(typeof(SerializationInfo
));
171 ArgumentReference arg2
= new ArgumentReference(typeof(StreamingContext
));
172 EasyMethod getObjectData
= MainTypeBuilder
.CreateMethod("GetObjectData",
173 new ReturnReferenceExpression(typeof(void)), arg1
, arg2
);
175 LocalReference typeLocal
= getObjectData
.CodeBuilder
.DeclareLocal(typeof(Type
));
177 getObjectData
.CodeBuilder
.AddStatement(new AssignStatement(
179 new MethodInvocationExpression(null,
180 typeof(Type
).GetMethod("GetType",
183 Context
.ProxyObjectReference
.
184 AssemblyQualifiedName
).ToExpression(),
185 new FixedReference(1).ToExpression(),
186 new FixedReference(0).ToExpression())));
188 getObjectData
.CodeBuilder
.AddStatement(new ExpressionStatement(
189 new VirtualMethodInvocationExpression(
190 arg1
, typeof(SerializationInfo
).GetMethod("SetType"),
191 typeLocal
.ToExpression())));
193 getObjectData
.CodeBuilder
.AddStatement(new ExpressionStatement(
194 new VirtualMethodInvocationExpression(arg1
, addValueMethod
,
195 new FixedReference("__interceptor").
197 InterceptorField
.ToExpression())));
199 getObjectData
.CodeBuilder
.AddStatement(new ExpressionStatement(
200 new VirtualMethodInvocationExpression(arg1
, addValueMethod
,
201 new FixedReference("__mixins").
203 MixinField
.ToExpression())));
205 LocalReference interfacesLocal
=
206 getObjectData
.CodeBuilder
.DeclareLocal(typeof(String
[]));
208 getObjectData
.CodeBuilder
.AddStatement(
209 new AssignStatement(interfacesLocal
,
210 new NewArrayExpression(interfaces
.Length
, typeof(String
))));
212 for(int i
= 0; i
< interfaces
.Length
; i
++)
214 getObjectData
.CodeBuilder
.AddStatement(new AssignArrayStatement(
216 new FixedReference(interfaces
[i
].AssemblyQualifiedName
).ToExpression()));
219 getObjectData
.CodeBuilder
.AddStatement(new ExpressionStatement(
220 new VirtualMethodInvocationExpression(arg1
, addValueMethod
,
221 new FixedReference("__interfaces").
223 interfacesLocal
.ToExpression())));
225 getObjectData
.CodeBuilder
.AddStatement(new ExpressionStatement(
226 new VirtualMethodInvocationExpression(arg1
, addValueMethod
,
227 new FixedReference("__baseType").
229 new TypeTokenExpression(_baseType
))));
231 CustomizeGetObjectData(getObjectData
.CodeBuilder
, arg1
, arg2
);
233 getObjectData
.CodeBuilder
.AddStatement(new ReturnStatement());
236 protected virtual void CustomizeGetObjectData(AbstractCodeBuilder codebuilder
, ArgumentReference arg1
,
237 ArgumentReference arg2
)
241 protected virtual void ImplementCacheInvocationCache()
243 MethodInfo get_ItemMethod
= typeof(HybridDictionary
).GetMethod("get_Item", new Type
[] {typeof(object)}
);
244 MethodInfo set_ItemMethod
= typeof(HybridDictionary
).GetMethod("Add", new Type
[] {typeof(object), typeof(object)}
);
246 Type
[] args
= new Type
[] {typeof(ICallable), typeof(MethodInfo)}
;
247 Type
[] invocation_const_args
= new Type
[] {typeof(ICallable), typeof(object), typeof(MethodInfo), typeof(object)}
;
249 ArgumentReference arg1
= new ArgumentReference(typeof(ICallable
));
250 ArgumentReference arg2
= new ArgumentReference(typeof(MethodInfo
));
251 ArgumentReference arg3
= new ArgumentReference(typeof(object));
253 _method2Invocation
= MainTypeBuilder
.CreateMethod("_Method2Invocation",
254 new ReturnReferenceExpression(Context
.Invocation
),
255 MethodAttributes
.Family
| MethodAttributes
.HideBySig
, arg1
, arg2
,
258 LocalReference invocation_local
=
259 _method2Invocation
.CodeBuilder
.DeclareLocal(Context
.Invocation
);
261 LockBlockExpression block
= new LockBlockExpression(SelfReference
.Self
);
263 block
.AddStatement(new AssignStatement(invocation_local
,
264 new ConvertExpression(Context
.Invocation
,
265 new VirtualMethodInvocationExpression(CacheField
,
267 arg2
.ToExpression()))));
269 ConditionExpression cond1
= new ConditionExpression(OpCodes
.Brfalse_S
,
270 invocation_local
.ToExpression());
272 cond1
.AddTrueStatement(new AssignStatement(
274 new NewInstanceExpression(InvocationType
.GetConstructor(invocation_const_args
),
275 arg1
.ToExpression(), SelfReference
.Self
.ToExpression(),
276 arg2
.ToExpression(), arg3
.ToExpression())));
278 cond1
.AddTrueStatement(new ExpressionStatement(
279 new VirtualMethodInvocationExpression(CacheField
,
280 set_ItemMethod
, arg2
.ToExpression(),
281 invocation_local
.ToExpression())));
283 block
.AddStatement(new ExpressionStatement(cond1
));
285 _method2Invocation
.CodeBuilder
.AddStatement(new ExpressionStatement(block
));
286 _method2Invocation
.CodeBuilder
.AddStatement(new ReturnStatement(invocation_local
));
289 protected virtual Type
[] AddInterfaces(Type
[] interfacesToAdd
, Type
[] interfaces
)
291 bool[] containsInterface
= new bool[interfacesToAdd
.Length
];
292 int interfacesToAddCount
= 0;
293 for(int i
= interfacesToAdd
.Length
- 1; i
>= 0; i
--)
295 containsInterface
[i
] = Array
.Exists(interfaces
, delegate(Type type
)
297 //May be somebody should revise this...
298 return interfacesToAdd
[i
].FullName
.Equals(type
.FullName
);
300 if (!containsInterface
[i
])
302 interfacesToAddCount
++;
306 Type
[] newList
= new Type
[interfaces
.Length
+ interfacesToAddCount
];
307 Array
.Copy(interfaces
, newList
, interfaces
.Length
);
308 int currentIndex
= interfaces
.Length
;
310 for(int i
= 0; i
< interfacesToAdd
.Length
; i
++)
312 if (!containsInterface
[i
]) // Proxy does not yet implement the interface...
314 newList
[currentIndex
++] = interfacesToAdd
[i
];
321 //For backward compatibility...
322 protected virtual Type
[] AddISerializable(Type
[] interfaces
)
324 return AddInterfaces(new Type
[] {typeof(ISerializable)}
, interfaces
);
327 protected virtual Type
CreateType()
329 Type newType
= MainTypeBuilder
.BuildType();
331 RegisterInCache(newType
);
337 /// Generates one public constructor receiving
338 /// the <see cref="IInterceptor"/> instance and instantiating a hashtable
341 /// Should be overrided to provided specific semantics, if necessary
343 protected virtual EasyConstructor
GenerateConstructor()
349 /// Common initializatio code for the default constructor
351 /// <param name="codebuilder"></param>
352 /// <param name="interceptorArg"></param>
353 /// <param name="targetArgument"></param>
354 /// <param name="mixinArray"></param>
355 protected virtual void GenerateConstructorCode(ConstructorCodeBuilder codebuilder
,
356 Reference interceptorArg
, Reference targetArgument
,
357 Reference mixinArray
)
359 codebuilder
.AddStatement(new AssignStatement(
360 InterceptorField
, interceptorArg
.ToExpression()));
362 int mixins
= Context
.MixinsAsArray().Length
;
364 codebuilder
.AddStatement(new AssignStatement(
365 MixinField
, new NewArrayExpression(mixins
, typeof(object))));
367 if (Context
.HasMixins
)
369 for(int i
= 0; i
< mixins
; i
++)
371 codebuilder
.AddStatement(new AssignArrayStatement(
373 new LoadRefArrayElementExpression(i
, mixinArray
)));
377 codebuilder
.AddStatement(new AssignStatement(
378 CacheField
, new NewInstanceExpression(
379 typeof(HybridDictionary
).GetConstructor(new Type
[0]))));
381 // Initialize the delegate fields
382 foreach(CallableField field
in _cachedFields
)
384 field
.WriteInitialization(codebuilder
, targetArgument
, mixinArray
);
388 protected ConstructorInfo
ObtainAvailableConstructor(Type target
)
391 target
.GetConstructor(BindingFlags
.Instance
| BindingFlags
.Public
| BindingFlags
.NonPublic
, null, new Type
[0], null);
397 /// <param name="interfaces"></param>
398 protected void GenerateInterfaceImplementation(Type
[] interfaces
)
400 foreach(Type inter
in interfaces
)
402 GenerateTypeImplementation(inter
, false);
407 /// Iterates over the interfaces and generate implementation
408 /// for each method in it.
410 /// <param name="type">Type class</param>
411 /// <param name="ignoreInterfaces">if true, we inspect the
412 /// type for implemented interfaces</param>
413 protected void GenerateTypeImplementation(Type type
, bool ignoreInterfaces
)
415 if (_generated
.Contains(type
)) return;
416 if (Context
.ShouldSkip(type
)) return;
418 _generated
.Add(type
);
420 if (!ignoreInterfaces
)
422 Type
[] baseInterfaces
= type
.FindInterfaces(new TypeFilter(NoFilterImpl
), type
);
423 GenerateInterfaceImplementation(baseInterfaces
);
426 EasyProperty
[] properties
= GenerateProperties(type
);
427 GenerateMethods(type
, properties
);
430 protected virtual EasyProperty
[] GenerateProperties(Type inter
)
432 PropertyInfo
[] properties
= inter
.GetProperties(BindingFlags
.Public
| BindingFlags
.NonPublic
| BindingFlags
.Instance
);
434 EasyProperty
[] propertiesBuilder
= new EasyProperty
[properties
.Length
];
436 for(int i
= 0; i
< properties
.Length
; i
++)
438 propertiesBuilder
[i
] = CreateProperty(properties
[i
]);
441 return propertiesBuilder
;
444 protected virtual void GenerateMethods(Type inter
, EasyProperty
[] properties
)
446 MethodInfo
[] methods
= inter
.GetMethods(BindingFlags
.Instance
| BindingFlags
.Public
| BindingFlags
.NonPublic
);
448 foreach(MethodInfo method
in methods
)
452 Context
.AddMethodToGenerateNewSlot(method
);
454 if (method
.IsPrivate
|| !method
.IsVirtual
|| method
.IsFinal
)
459 if (method
.IsAssembly
&& !IsInternalToDynamicProxy(method
.Module
.Assembly
))
461 if (method
.IsAssembly
&& !IsInternalToDynamicProxy(inter
.Assembly
))
466 if (method
.DeclaringType
.Equals(typeof(Object
)) && !method
.IsVirtual
)
470 if (method
.DeclaringType
.Equals(typeof(Object
)) && "Finalize".Equals(method
.Name
))
475 GenerateMethodImplementation(method
, properties
);
480 /// Naive implementation, but valid for long namespaces
481 /// Works by using only the last piece of the namespace
483 protected String
NormalizeNamespaceName(String nsName
)
485 if (nsName
== null || nsName
== String
.Empty
) return String
.Empty
;
487 String
[] parts
= nsName
.Split('.', '+');
489 return parts
[parts
.Length
- 1];
493 /// Gets the name of a type, taking into consideration nested types.
495 protected String
GetTypeName(Type type
)
497 System
.Text
.StringBuilder nameBuilder
= new System
.Text
.StringBuilder();
498 if (type
.Namespace
!= null)
500 nameBuilder
.Append(type
.Namespace
.Replace('.', '_'));
502 if (type
.DeclaringType
!= null)
504 nameBuilder
.Append(type
.DeclaringType
.Name
).Append("_");
507 if (type
.IsGenericType
)
509 Type
[] args
= type
.GetGenericArguments();
510 foreach (Type arg
in args
)
512 string argName
= GetTypeName(arg
);
513 nameBuilder
.Append(argName
).Append("_");
519 nameBuilder
.Append("ArrayOf").Append(GetTypeName(type
.GetElementType()));
523 nameBuilder
.Append(type
.Name
);
525 return nameBuilder
.ToString();
529 /// Generate property implementation
531 /// <param name="property"></param>
532 protected virtual EasyProperty
CreateProperty(PropertyInfo property
)
534 return _typeBuilder
.CreateProperty(property
);
538 /// Generates implementation for each method.
540 /// <param name="method"></param>
541 /// <param name="properties"></param>
542 protected void GenerateMethodImplementation(MethodInfo method
, EasyProperty
[] properties
)
544 if (Context
.ShouldSkip(method
)) return;
546 ParameterInfo
[] parametersInfo
= method
.GetParameters();
548 Type
[] parameters
= new Type
[parametersInfo
.Length
];
550 for(int i
= 0; i
< parametersInfo
.Length
; i
++)
552 parameters
[i
] = parametersInfo
[i
].ParameterType
;
555 MethodAttributes atts
= ObtainMethodAttributes(method
);
557 PreProcessMethod(method
);
559 EasyMethod easyMethod
= null;
561 bool isSetMethod
= method
.IsSpecialName
&& method
.Name
.StartsWith("set_");
562 bool isGetMethod
= method
.IsSpecialName
&& method
.Name
.StartsWith("get_");
564 if (!isSetMethod
&& !isGetMethod
)
566 easyMethod
= _typeBuilder
.CreateMethod(method
.Name
,
567 atts
, new ReturnReferenceExpression(method
.ReturnType
), parameters
);
571 if (isSetMethod
|| isGetMethod
)
573 foreach(EasyProperty property
in properties
)
575 if (property
== null)
580 if (!property
.Name
.Equals(method
.Name
.Substring(4)))
585 if (property
.IndexParameters
!= null)
587 bool signatureMatches
= true;
588 int numOfIndexes
= parametersInfo
.Length
;
589 //A set method already has a value parameter, and everything after
590 //that is an indexer.
593 if (numOfIndexes
!= property
.IndexParameters
.Length
)
595 for(int i
= 0; i
< property
.IndexParameters
.Length
; i
++)
597 if (property
.IndexParameters
[i
].ParameterType
!= parametersInfo
[i
].ParameterType
)
599 signatureMatches
= false;
604 if (!signatureMatches
) continue;
609 easyMethod
= property
.CreateSetMethod(atts
, parameters
);
614 easyMethod
= property
.CreateGetMethod(atts
, parameters
);
621 easyMethod
.DefineParameters(parametersInfo
);
623 WriteInterceptorInvocationMethod(method
, easyMethod
);
625 PostProcessMethod(method
);
628 private MethodAttributes
ObtainMethodAttributes(MethodInfo method
)
630 MethodAttributes atts
;
631 if (Context
.ShouldCreateNewSlot(method
))
632 atts
= MethodAttributes
.NewSlot
;
634 atts
= MethodAttributes
.Virtual
;
638 atts
|= MethodAttributes
.Public
;
640 if (IsInternalToDynamicProxy(method
.DeclaringType
.Assembly
) && method
.IsAssembly
)
642 atts
|= MethodAttributes
.Assembly
;
644 if (method
.IsHideBySig
)
646 atts
|= MethodAttributes
.HideBySig
;
649 if (method
.IsFamilyAndAssembly
)
651 atts
|= MethodAttributes
.FamANDAssem
;
653 else if (method
.IsFamilyOrAssembly
)
655 atts
|= MethodAttributes
.FamORAssem
;
657 else if (method
.IsFamily
)
659 atts
|= MethodAttributes
.Family
;
662 if (method
.Name
.StartsWith("set_") || method
.Name
.StartsWith("get_"))
664 atts
|= MethodAttributes
.SpecialName
;
669 protected virtual void PreProcessMethod(MethodInfo method
)
671 MethodInfo callbackMethod
= GenerateCallbackMethodIfNecessary(method
, null);
673 EasyCallable callable
= MainTypeBuilder
.CreateCallable(method
.ReturnType
, method
.GetParameters());
675 _method2Delegate
[method
] = callable
;
677 FieldReference field
= MainTypeBuilder
.CreateField(
678 String
.Format("_cached_{0}", callable
.ID
),
679 callable
.TypeBuilder
);
681 RegisterDelegateFieldToBeInitialized(method
, field
, callable
, callbackMethod
);
684 protected virtual MethodInfo
GenerateCallbackMethodIfNecessary(MethodInfo method
, Reference invocationTarget
)
686 if (Context
.HasMixins
&& _interface2mixinIndex
.Contains(method
.DeclaringType
))
691 String name
= String
.Format("callback__{0}", method
.Name
);
693 ParameterInfo
[] parameters
= method
.GetParameters();
695 ArgumentReference
[] args
= new ArgumentReference
[parameters
.Length
];
697 for(int i
= 0; i
< args
.Length
; i
++)
699 args
[i
] = new ArgumentReference(parameters
[i
].ParameterType
);
702 EasyMethod easymethod
= MainTypeBuilder
.CreateMethod(name
,
703 new ReturnReferenceExpression(method
.ReturnType
),
704 MethodAttributes
.HideBySig
| MethodAttributes
.Public
, args
);
706 Expression
[] exps
= new Expression
[parameters
.Length
];
708 for(int i
= 0; i
< args
.Length
; i
++)
710 exps
[i
] = args
[i
].ToExpression();
713 if (invocationTarget
== null)
715 easymethod
.CodeBuilder
.AddStatement(
717 new MethodInvocationExpression(method
, exps
)));
721 easymethod
.CodeBuilder
.AddStatement(
723 new MethodInvocationExpression(invocationTarget
, method
, exps
)));
726 return easymethod
.MethodBuilder
;
729 protected virtual void PostProcessMethod(MethodInfo method
)
734 /// Writes the method implementation. This
735 /// method generates the IL code for property get/set method and
736 /// ordinary methods.
738 /// <param name="method">The method to implement.</param>
739 /// <param name="builder"><see cref="EasyMethod"/> being constructed.</param>
740 protected virtual void WriteInterceptorInvocationMethod(MethodInfo method
, EasyMethod builder
)
742 ArgumentReference
[] arguments
= builder
.Arguments
;
743 TypeReference
[] dereferencedArguments
= IndirectReference
.WrapIfByRef(builder
.Arguments
);
745 LocalReference local_inv
= builder
.CodeBuilder
.DeclareLocal(Context
.Invocation
);
747 EasyCallable callable
= _method2Delegate
[method
] as EasyCallable
;
748 FieldReference fieldDelegate
= ObtainCallableFieldBuilderDelegate(callable
);
750 builder
.CodeBuilder
.AddStatement(
751 new AssignStatement(local_inv
,
752 new MethodInvocationExpression(_method2Invocation
,
753 fieldDelegate
.ToExpression(),
754 new MethodTokenExpression(GetCorrectMethod(method
)),
755 GetPseudoInvocationTarget(method
))));
757 LocalReference ret_local
= builder
.CodeBuilder
.DeclareLocal(typeof(object));
758 LocalReference args_local
= builder
.CodeBuilder
.DeclareLocal(typeof(object[]));
760 // Store arguments into an object array.
761 builder
.CodeBuilder
.AddStatement(
762 new AssignStatement(args_local
,
763 new ReferencesToObjectArrayExpression(dereferencedArguments
)));
765 // Invoke the interceptor.
766 builder
.CodeBuilder
.AddStatement(
767 new AssignStatement(ret_local
,
768 new VirtualMethodInvocationExpression(InterceptorField
,
769 Context
.Interceptor
.GetMethod("Intercept"),
770 local_inv
.ToExpression(),
771 args_local
.ToExpression())));
773 // Load possibly modified ByRef arguments from the array.
774 for(int i
= 0; i
< arguments
.Length
; i
++)
776 if (arguments
[i
].Type
.IsByRef
)
778 builder
.CodeBuilder
.AddStatement(
779 new AssignStatement(dereferencedArguments
[i
],
780 new ConvertExpression(dereferencedArguments
[i
].Type
,
781 new LoadRefArrayElementExpression(i
, args_local
))));
785 if (builder
.ReturnType
== typeof(void))
787 builder
.CodeBuilder
.AddStatement(new ReturnStatement());
791 builder
.CodeBuilder
.AddStatement(new ReturnStatement(
792 new ConvertExpression(builder
.ReturnType
, ret_local
.ToExpression())));
796 protected virtual Expression
GetPseudoInvocationTarget(MethodInfo method
)
798 return NullExpression
.Instance
;
801 protected virtual MethodInfo
GetCorrectMethod(MethodInfo method
)
806 protected Type
[] InspectAndRegisterInterfaces(object[] mixins
)
808 if (mixins
== null) return new Type
[0];
810 Set interfaces
= new Set();
812 for(int i
= 0; i
< mixins
.Length
; ++i
)
814 object mixin
= mixins
[i
];
816 Type
[] mixinInterfaces
= mixin
.GetType().GetInterfaces();
817 mixinInterfaces
= Filter(mixinInterfaces
);
819 interfaces
.AddArray(mixinInterfaces
);
821 // Later we gonna need to say which mixin
822 // handle the method of a specific interface
823 foreach(Type inter
in mixinInterfaces
)
825 _interface2mixinIndex
.Add(inter
, i
);
829 return (Type
[]) interfaces
.ToArray(typeof(Type
));
832 protected Type
[] Filter(Type
[] mixinInterfaces
)
834 ArrayList retType
= new ArrayList();
835 foreach(Type type
in mixinInterfaces
)
837 if (!Context
.ShouldSkip(type
))
841 return (Type
[]) retType
.ToArray(typeof(Type
));
844 public static bool NoFilterImpl(Type type
, object criteria
)
849 protected bool IsInternalToDynamicProxy(Assembly asm
)
852 internalsToDynProxyLock
.AcquireReaderLock(-1);
854 if (internalsToDynProxy
.ContainsKey(asm
))
856 internalsToDynProxyLock
.ReleaseReaderLock();
858 return internalsToDynProxy
[asm
];
861 internalsToDynProxyLock
.UpgradeToWriterLock(-1);
865 if (internalsToDynProxy
.ContainsKey(asm
))
867 return internalsToDynProxy
[asm
];
870 InternalsVisibleToAttribute
[] atts
= (InternalsVisibleToAttribute
[])
871 asm
.GetCustomAttributes(typeof(InternalsVisibleToAttribute
), false);
875 foreach(InternalsVisibleToAttribute internals
in atts
)
877 if (internals
.AssemblyName
.Contains(ModuleScope
.ASSEMBLY_NAME
))
884 internalsToDynProxy
.Add(asm
, found
);
890 internalsToDynProxyLock
.ReleaseWriterLock();
901 internal class CallableField
903 private FieldReference _field
;
904 private EasyCallable _callable
;
905 private MethodInfo _callback
;
906 private int _sourceArgIndex
;
908 public CallableField(FieldReference field
, EasyCallable callable
,
909 MethodInfo callback
, int sourceArgIndex
)
912 _callable
= callable
;
913 _callback
= callback
;
914 _sourceArgIndex
= sourceArgIndex
;
917 public FieldReference Field
919 get { return _field; }
922 public EasyCallable Callable
924 get { return _callable; }
927 public int SourceArgIndex
929 get { return _sourceArgIndex; }
932 public void WriteInitialization(AbstractCodeBuilder codebuilder
,
933 Reference targetArgument
, Reference mixinArray
)
935 NewInstanceExpression newInst
= null;
937 if (SourceArgIndex
== EmptyIndex
)
939 newInst
= new NewInstanceExpression(Callable
,
940 targetArgument
.ToExpression(), new MethodPointerExpression(_callback
));
944 newInst
= new NewInstanceExpression(Callable
,
945 new LoadRefArrayElementExpression(SourceArgIndex
, mixinArray
),
946 new MethodPointerExpression(_callback
));
949 codebuilder
.AddStatement(new AssignStatement(
953 public static int EmptyIndex