using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Other; using ILRuntime.Mono.Cecil; using ILRuntime.Runtime.Intepreter; using System.Reflection; using ILRuntime.Reflection; namespace ILRuntime.CLR.Utils { public delegate TResult Func(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); public static class Extensions { public static List EmptyParamList = new List(); public static List GetParamList(this MethodReference def, ILRuntime.Runtime.Enviorment.AppDomain appdomain, IType contextType, IMethod contextMethod, IType[] genericArguments) { if (def.HasParameters) { List param = new List(); var dt = appdomain.GetType(def.DeclaringType, contextType, contextMethod); foreach (var i in def.Parameters) { IType t = null; t = appdomain.GetType(i.ParameterType, dt, null); if ((t == null && def.IsGenericInstance) || (t != null && t.HasGenericParameter)) { GenericInstanceMethod gim = (GenericInstanceMethod)def; string name = i.ParameterType.IsByReference ? ((ByReferenceType)i.ParameterType).ElementType.FullName : i.ParameterType.FullName; for (int j = 0; j < gim.GenericArguments.Count; j++) { var gp = gim.ElementMethod.GenericParameters[j]; var ga = gim.GenericArguments[j]; if (name == gp.Name) { t = appdomain.GetType(ga, contextType, contextMethod); if (t == null && genericArguments != null) t = genericArguments[j]; break; } else if (name.Contains(gp.Name)) { t = appdomain.GetType(ga, contextType, contextMethod); if (t == null && genericArguments != null) t = genericArguments[j]; if (name == gp.Name + "[]") { name = t.FullName + "[]"; } else { /*name = name.Replace("<" + gp.Name + ">", "<" + ga.FullName + ">"); name = name.Replace("<" + gp.Name + "[", "<" + ga.FullName + "["); name = name.Replace("<" + gp.Name + ",", "<" + ga.FullName + ","); name = name.Replace("," + gp.Name + ">", "," + ga.FullName + ">"); name = name.Replace("," + gp.Name + "[", "," + ga.FullName + "["); name = name.Replace("," + gp.Name + ",", "," + ga.FullName + ","); name = name.Replace("," + gp.Name + "[", "," + ga.FullName + "[");*/ name = ReplaceGenericArgument(name, gp.Name, t.FullName); } t = null; } } if(dt.GenericArguments != null) { foreach(var gp in dt.GenericArguments) { if (name.Contains(gp.Key)) { name = ReplaceGenericArgument(name, gp.Key, gp.Value.FullName); } } } if (t == null) t = appdomain.GetType(name); if (t != null && i.ParameterType.IsByReference) t = t.MakeByRefType(); } param.Add(t); } return param; } else return EmptyParamList; } static string ReplaceGenericArgument(string typename, string argumentName, string argumentType, bool isGA = false) { string baseType; StringBuilder sb = new StringBuilder(); List ga; bool isArray; byte rank; Runtime.Enviorment.AppDomain.ParseGenericType(typename, out baseType, out ga, out isArray, out rank); string baseTypeQualification = null; bool hasGA = ga != null && ga.Count > 0; if (baseType == argumentName) { bool isAssemblyQualified = argumentName.Contains('=') || argumentType.Contains('='); if (isGA && isAssemblyQualified) sb.Append('['); sb.Append(argumentType); if (isGA && isAssemblyQualified) sb.Append(']'); } else { if (baseType.Contains("[")) { baseType = ReplaceGenericArgument(baseType, argumentName, argumentType, isGA); } bool isAssemblyQualified = baseType.Contains('='); if (isGA && !hasGA && isAssemblyQualified) sb.Append('['); else if (isAssemblyQualified) { sb.Append('['); baseTypeQualification = baseType.Substring(baseType.IndexOf(',')); baseType = baseType.Substring(0, baseType.IndexOf(',')); } sb.Append(baseType); if (isGA && !hasGA && isAssemblyQualified) sb.Append(']'); } if (hasGA) { sb.Append("["); bool isFirst = true; foreach (var i in ga) { if (isFirst) isFirst = false; else sb.Append(","); sb.Append(ReplaceGenericArgument(i, argumentName, argumentType, true)); } sb.Append("]"); } if (!string.IsNullOrEmpty(baseTypeQualification)) { sb.Append(baseTypeQualification); sb.Append(']'); } if (isArray) { sb.Append("["); for (int i = 0; i < rank - 1; i++) sb.Append(","); sb.Append("]"); } return sb.ToString(); } [Flags] public enum TypeFlags { Default = 0, IsPrimitive = 0x1, IsByRef = 0x2, IsEnum = 0x4, IsDelegate = 0x8, IsValueType = 0x10, } private static readonly Dictionary typeFlags = new Dictionary(new ByReferenceKeyComparer()); public static bool FastIsEnum(this Type pt) { return (pt.GetTypeFlags() & TypeFlags.IsEnum) != 0; } public static bool FastIsByRef(this Type pt) { return (pt.GetTypeFlags() & TypeFlags.IsByRef) != 0; } public static bool FastIsPrimitive(this Type pt) { return (pt.GetTypeFlags() & TypeFlags.IsPrimitive) != 0; } public static bool FastIsValueType(this Type pt) { return (pt.GetTypeFlags() & TypeFlags.IsValueType) != 0; } public static TypeFlags GetTypeFlagsRecursive(this Type pt) { var res = GetTypeFlags(pt); if ((res & TypeFlags.IsByRef) == TypeFlags.IsByRef) res = GetTypeFlagsRecursive(pt.GetElementType()); return res; } public static TypeFlags GetTypeFlags(this Type pt) { var result = TypeFlags.Default; if (!typeFlags.TryGetValue(pt, out result)) { if (pt.IsPrimitive) { result |= TypeFlags.IsPrimitive; } if (pt == typeof(Delegate) || pt.IsSubclassOf(typeof(Delegate))) { result |= TypeFlags.IsDelegate; } if (pt.IsByRef) { result |= TypeFlags.IsByRef; } if (pt.IsEnum) { result |= TypeFlags.IsEnum; } if (pt.IsValueType) { result |= TypeFlags.IsValueType; } typeFlags[pt] = result; } return result; } public static object CheckCLRTypes(this Type pt, object obj) { var typeFlags = GetTypeFlags(pt); return CheckCLRTypes(pt, obj, typeFlags); } public static object CheckCLRTypes(this Type pt, object obj, TypeFlags typeFlags) { if (obj == null) return null; if ((typeFlags & TypeFlags.IsPrimitive) != 0) { if (pt == typeof(int)) return obj; if (pt == typeof(bool) && !(obj is bool)) { obj = (int)obj == 1; } else if (pt == typeof(byte) && !(obj is byte)) obj = (byte)(int)obj; else if (pt == typeof(short) && !(obj is short)) obj = (short)(int)obj; else if (pt == typeof(char) && !(obj is char)) obj = (char)(int)obj; else if (pt == typeof(ushort) && !(obj is ushort)) obj = (ushort)(int)obj; else if (pt == typeof(uint) && !(obj is uint)) obj = (uint)(int)obj; else if (pt == typeof(sbyte) && !(obj is sbyte)) obj = (sbyte)(int)obj; else if (pt == typeof(ulong) && !(obj is ulong)) { obj = (ulong)(long)obj; } } else if (obj is ILRuntime.Reflection.ILRuntimeWrapperType) { obj = ((ILRuntime.Reflection.ILRuntimeWrapperType)obj).RealType; } else if ((typeFlags & TypeFlags.IsDelegate) != 0) { if (obj is Delegate) return obj; if (pt == typeof(Delegate)) return ((IDelegateAdapter)obj).Delegate; return ((IDelegateAdapter)obj).GetConvertor(pt); } else if ((typeFlags & TypeFlags.IsByRef) != 0) { return CheckCLRTypes(pt.GetElementType(), obj); } else if ((typeFlags & TypeFlags.IsEnum) != 0) { return Enum.ToObject(pt, obj); } else if (obj is ILTypeInstance) { var adapter = obj as IDelegateAdapter; if (adapter != null && pt != typeof(ILTypeInstance)) { return adapter.Delegate; } if (!(obj is ILEnumTypeInstance)) { var ins = (ILTypeInstance)obj; /*if (ins.IsValueType) ins = ins.Clone();*/ return ins.CLRInstance; } } return obj; } public static bool CheckMethodParams(this MethodInfo m, Type[] args) { var arr = m.GetParameters(); if (arr.Length != args.Length) return false; for (var i = 0; i < args.Length; i++) { var t1 = arr[i].ParameterType; var t2 = args[i]; if (t1 != t2 || t1.IsByRef != t2.IsByRef) return false; } return true; } public static bool CheckMethodParams(this MethodInfo m, ParameterInfo[] args) { var arr = m.GetParameters(); if (arr.Length != args.Length) return false; for (var i = 0; i < args.Length; i++) { var t1 = arr[i].ParameterType; var t2 = args[i].ParameterType; if (t1 != t2 || t1.IsByRef != t2.IsByRef) return false; } return true; } public static Type UnWrapper(this Type type) { if (type is ILRuntimeWrapperType) return (type as ILRuntimeWrapperType).RealType; return type; } } }