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
.Generators
.Emitters
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
)
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
>
54 DefineGenericArguments(genericArguments
, name2GenericType
,
55 delegate(String
[] args
) { return builder.DefineGenericParameters(args); }
);
58 private static GenericTypeParameterBuilder
[] DefineGenericArguments(
59 Type
[] genericArguments
,
60 Dictionary
<String
, GenericTypeParameterBuilder
>
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
++)
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
)
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
);
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(
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
];
182 return genericType
.MakeArrayType();
186 return genericType
.MakeArrayType(rank
);
193 return underlyingType
.MakeArrayType();
197 return underlyingType
.MakeArrayType(rank
);
202 if (paramType
.IsGenericParameter
)
204 return name2GenericType
[paramType
.Name
];
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
;