Added generalized installation capabilities to Windsor (analogous to Kernel registration)
[castle.git] / Tools / DynamicProxy / Castle.DynamicProxy / Builder / CodeGenerators / BaseCodeGenerator.cs
blobfb32d04e4e2889f6ee6ad8aea9dd0a74faf24729
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
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
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
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
17 using System;
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;
26 #if DOTNET2
27 using System.Runtime.CompilerServices;
28 #endif
30 /// <summary>
31 /// Summary description for BaseCodeGenerator.
32 /// </summary>
33 [CLSCompliant(false)]
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();
44 #if DOTNET2
45 private ReaderWriterLock internalsToDynProxyLock = new ReaderWriterLock();
46 private System.Collections.Generic.IDictionary<Assembly, bool> internalsToDynProxy = new System.Collections.Generic.Dictionary<Assembly, bool>();
47 #endif
48 protected Type _baseType = typeof(Object);
49 protected EasyMethod _method2Invocation;
50 protected object[] _mixins = new object[0];
52 /// <summary>
53 /// Holds instance fields which points to delegates instantiated
54 /// </summary>
55 protected ArrayList _cachedFields = new ArrayList();
57 /// <summary>
58 /// MethodInfo => Callable delegate
59 /// </summary>
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;
72 _context = context;
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)
123 return field.Field;
127 return null;
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);
149 return _typeBuilder;
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(
178 typeLocal,
179 new MethodInvocationExpression(null,
180 typeof(Type).GetMethod("GetType",
181 get_type_args),
182 new FixedReference(
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").
196 ToExpression(),
197 InterceptorField.ToExpression())));
199 getObjectData.CodeBuilder.AddStatement(new ExpressionStatement(
200 new VirtualMethodInvocationExpression(arg1, addValueMethod,
201 new FixedReference("__mixins").
202 ToExpression(),
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(
215 interfacesLocal, i,
216 new FixedReference(interfaces[i].AssemblyQualifiedName).ToExpression()));
219 getObjectData.CodeBuilder.AddStatement(new ExpressionStatement(
220 new VirtualMethodInvocationExpression(arg1, addValueMethod,
221 new FixedReference("__interfaces").
222 ToExpression(),
223 interfacesLocal.ToExpression())));
225 getObjectData.CodeBuilder.AddStatement(new ExpressionStatement(
226 new VirtualMethodInvocationExpression(arg1, addValueMethod,
227 new FixedReference("__baseType").
228 ToExpression(),
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,
256 arg3);
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,
266 get_ItemMethod,
267 arg2.ToExpression()))));
269 ConditionExpression cond1 = new ConditionExpression(OpCodes.Brfalse_S,
270 invocation_local.ToExpression());
272 cond1.AddTrueStatement(new AssignStatement(
273 invocation_local,
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];
318 return newList;
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);
333 return newType;
336 /// <summary>
337 /// Generates one public constructor receiving
338 /// the <see cref="IInterceptor"/> instance and instantiating a hashtable
339 /// </summary>
340 /// <remarks>
341 /// Should be overrided to provided specific semantics, if necessary
342 /// </remarks>
343 protected virtual EasyConstructor GenerateConstructor()
345 return null;
348 /// <summary>
349 /// Common initializatio code for the default constructor
350 /// </summary>
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(
372 MixinField, i,
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)
390 return
391 target.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null);
394 /// <summary>
395 ///
396 /// </summary>
397 /// <param name="interfaces"></param>
398 protected void GenerateInterfaceImplementation(Type[] interfaces)
400 foreach(Type inter in interfaces)
402 GenerateTypeImplementation(inter, false);
406 /// <summary>
407 /// Iterates over the interfaces and generate implementation
408 /// for each method in it.
409 /// </summary>
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)
450 if (method.IsFinal)
452 Context.AddMethodToGenerateNewSlot(method);
454 if (method.IsPrivate || !method.IsVirtual || method.IsFinal)
456 continue;
458 #if DOTNET2
459 if (method.IsAssembly && !IsInternalToDynamicProxy(method.Module.Assembly))
460 #else
461 if (method.IsAssembly && !IsInternalToDynamicProxy(inter.Assembly))
462 #endif
464 continue;
466 if (method.DeclaringType.Equals(typeof(Object)) && !method.IsVirtual)
468 continue;
470 if (method.DeclaringType.Equals(typeof(Object)) && "Finalize".Equals(method.Name))
472 continue;
475 GenerateMethodImplementation(method, properties);
479 /// <summary>
480 /// Naive implementation, but valid for long namespaces
481 /// Works by using only the last piece of the namespace
482 /// </summary>
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];
492 /// <summary>
493 /// Gets the name of a type, taking into consideration nested types.
494 /// </summary>
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("_");
506 #if DOTNET2
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("_");
516 #endif
517 if (type.IsArray)
519 nameBuilder.Append("ArrayOf").Append(GetTypeName(type.GetElementType()));
521 else
523 nameBuilder.Append(type.Name);
525 return nameBuilder.ToString();
528 /// <summary>
529 /// Generate property implementation
530 /// </summary>
531 /// <param name="property"></param>
532 protected virtual EasyProperty CreateProperty(PropertyInfo property)
534 return _typeBuilder.CreateProperty(property);
537 /// <summary>
538 /// Generates implementation for each method.
539 /// </summary>
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);
569 else
571 if (isSetMethod || isGetMethod)
573 foreach(EasyProperty property in properties)
575 if (property == null)
577 break;
580 if (!property.Name.Equals(method.Name.Substring(4)))
582 continue;
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.
591 if (isSetMethod)
592 numOfIndexes--;
593 if (numOfIndexes != property.IndexParameters.Length)
594 continue;
595 for(int i = 0; i < property.IndexParameters.Length; i++)
597 if (property.IndexParameters[i].ParameterType != parametersInfo[i].ParameterType)
599 signatureMatches = false;
600 break;
604 if (!signatureMatches) continue;
607 if (isSetMethod)
609 easyMethod = property.CreateSetMethod(atts, parameters);
610 break;
612 else
614 easyMethod = property.CreateGetMethod(atts, parameters);
615 break;
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;
633 else
634 atts = MethodAttributes.Virtual;
636 if (method.IsPublic)
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;
666 return atts;
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))
688 return method;
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(
716 new ReturnStatement(
717 new MethodInvocationExpression(method, exps)));
719 else
721 easymethod.CodeBuilder.AddStatement(
722 new ReturnStatement(
723 new MethodInvocationExpression(invocationTarget, method, exps)));
726 return easymethod.MethodBuilder;
729 protected virtual void PostProcessMethod(MethodInfo method)
733 /// <summary>
734 /// Writes the method implementation. This
735 /// method generates the IL code for property get/set method and
736 /// ordinary methods.
737 /// </summary>
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());
789 else
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)
803 return 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))
838 retType.Add(type);
841 return (Type[]) retType.ToArray(typeof(Type));
844 public static bool NoFilterImpl(Type type, object criteria)
846 return true;
849 protected bool IsInternalToDynamicProxy(Assembly asm)
851 #if DOTNET2
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);
873 bool found = false;
875 foreach(InternalsVisibleToAttribute internals in atts)
877 if (internals.AssemblyName.Contains(ModuleScope.ASSEMBLY_NAME))
879 found = true;
880 break;
884 internalsToDynProxy.Add(asm, found);
886 return found;
888 finally
890 internalsToDynProxyLock.ReleaseWriterLock();
892 #else
893 return false;
894 #endif
898 /// <summary>
899 ///
900 /// </summary>
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)
911 _field = field;
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));
942 else
944 newInst = new NewInstanceExpression(Callable,
945 new LoadRefArrayElementExpression(SourceArgIndex, mixinArray),
946 new MethodPointerExpression(_callback));
949 codebuilder.AddStatement(new AssignStatement(
950 Field, newInst));
953 public static int EmptyIndex
955 get { return -1; }