testing commit notification
[castle.git] / Tools / Castle.DynamicProxy2 / Castle.DynamicProxy / Generators / Emitters / GenericUtil.cs
blobf096c19458d5eb1c3c9be3abd14a6716fcdf141c
1 // Copyright 2004-2007 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.Generators.Emitters
17 using System;
18 using System.Collections.Generic;
19 using System.Reflection;
20 using System.Reflection.Emit;
22 internal delegate GenericTypeParameterBuilder[] ApplyGenArgs(String[] argumentNames);
24 internal class GenericUtil
26 public static void PopulateGenericArguments(
27 AbstractTypeEmitter parentEmitter,
28 Dictionary<String, GenericTypeParameterBuilder> name2GenericType)
30 if (parentEmitter.GenericTypeParams == null) return;
32 foreach(GenericTypeParameterBuilder genType in parentEmitter.GenericTypeParams)
34 name2GenericType.Add(genType.Name, genType);
38 public static GenericTypeParameterBuilder[] DefineGenericArguments(
39 Type[] genericArguments, TypeBuilder builder,
40 Dictionary<String, GenericTypeParameterBuilder> name2GenericType)
42 return
43 DefineGenericArguments(genericArguments, name2GenericType,
44 delegate(String[] args) { return builder.DefineGenericParameters(args); });
47 public static GenericTypeParameterBuilder[] DefineGenericArguments(
48 Type[] genericArguments,
49 MethodBuilder builder,
50 Dictionary<String, GenericTypeParameterBuilder>
51 name2GenericType)
53 return
54 DefineGenericArguments(genericArguments, name2GenericType,
55 delegate(String[] args) { return builder.DefineGenericParameters(args); });
58 private static GenericTypeParameterBuilder[] DefineGenericArguments(
59 Type[] genericArguments,
60 Dictionary<String, GenericTypeParameterBuilder>
61 name2GenericType,
62 ApplyGenArgs gen)
64 GenericTypeParameterBuilder[] genericTypeParams = null;
66 String[] argumentNames = new String[genericArguments.Length];
68 for(int i = 0; i < argumentNames.Length; i++)
70 argumentNames[i] = genericArguments[i].Name;
73 if (argumentNames.Length != 0)
75 genericTypeParams = gen(argumentNames);
77 for(int i = 0; i < genericTypeParams.Length; i++)
79 try
81 GenericParameterAttributes attributes = genericArguments[i].GenericParameterAttributes;
82 Type[] types = genericArguments[i].GetGenericParameterConstraints();
84 genericTypeParams[i].SetGenericParameterAttributes(attributes);
86 Type[] interfacesConstraints = Array.FindAll(types, delegate(Type type) { return type.IsInterface; });
88 Type baseClassConstraint = Array.Find(types, delegate(Type type) { return type.IsClass; });
90 if (interfacesConstraints.Length != 0)
92 for(int j = 0; j < interfacesConstraints.Length; ++j)
94 interfacesConstraints[j] =
95 SubstituteGenericArguments(interfacesConstraints[j], genericArguments, genericTypeParams);
97 genericTypeParams[i].SetInterfaceConstraints(interfacesConstraints);
100 if (baseClassConstraint != null)
102 baseClassConstraint = SubstituteGenericArguments(baseClassConstraint, genericArguments, genericTypeParams);
103 genericTypeParams[i].SetBaseTypeConstraint(baseClassConstraint);
106 catch(NotSupportedException)
108 // Doesnt matter
110 genericTypeParams[i].SetGenericParameterAttributes(GenericParameterAttributes.None);
113 if (name2GenericType.ContainsKey(argumentNames[i]))
115 name2GenericType.Remove(argumentNames[i]);
118 name2GenericType.Add(argumentNames[i], genericTypeParams[i]);
122 return genericTypeParams;
125 private static Type SubstituteGenericArguments(
126 Type type, Type[] argumentsToSubstitute, GenericTypeParameterBuilder[] substitutes)
128 if (type.IsGenericType)
130 Type[] genericArguments = type.GetGenericArguments();
131 type = type.GetGenericTypeDefinition();
133 for(int i = 0; i < genericArguments.Length; ++i)
135 int substitutionIndex = Array.IndexOf(argumentsToSubstitute, genericArguments[i]);
136 if (substitutionIndex != -1)
138 genericArguments[i] = substitutes[substitutionIndex];
141 return type.MakeGenericType(genericArguments);
143 else
145 return type;
149 public static Type[] ExtractParametersTypes(
150 ParameterInfo[] baseMethodParameters,
151 Dictionary<String, GenericTypeParameterBuilder> name2GenericType)
153 Type[] newParameters = new Type[baseMethodParameters.Length];
155 for(int i = 0; i < baseMethodParameters.Length; i++)
157 ParameterInfo param = baseMethodParameters[i];
158 Type paramType = param.ParameterType;
160 newParameters[i] = ExtractCorrectType(paramType, name2GenericType);
163 return newParameters;
166 public static Type ExtractCorrectType(
167 Type paramType,
168 Dictionary<string, GenericTypeParameterBuilder> name2GenericType)
170 if (paramType.IsArray)
172 int rank = paramType.GetArrayRank();
174 Type underlyingType = paramType.GetElementType();
176 if (underlyingType.IsGenericParameter)
178 GenericTypeParameterBuilder genericType = name2GenericType[underlyingType.Name];
180 if (rank == 1)
182 return genericType.MakeArrayType();
184 else
186 return genericType.MakeArrayType(rank);
189 else
191 if (rank == 1)
193 return underlyingType.MakeArrayType();
195 else
197 return underlyingType.MakeArrayType(rank);
202 if (paramType.IsGenericParameter)
204 return name2GenericType[paramType.Name];
207 return paramType;
210 public static Type[] ExtractParameterTypes(ParameterInfo[] baseMethodParameters)
212 Type[] newParameters = new Type[baseMethodParameters.Length];
214 for(int i = 0; i < baseMethodParameters.Length; i++)
216 ParameterInfo param = baseMethodParameters[i];
217 Type paramType = param.ParameterType;
219 newParameters[i] = paramType;
222 return newParameters;