You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

349 lines
13 KiB

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, T2, T3, T4, T5, TResult>(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
public static class Extensions
{
public static List<IType> EmptyParamList = new List<IType>();
public static List<IType> GetParamList(this MethodReference def, ILRuntime.Runtime.Enviorment.AppDomain appdomain, IType contextType, IMethod contextMethod, IType[] genericArguments)
{
if (def.HasParameters)
{
List<IType> param = new List<IType>();
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<string> 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<Type, TypeFlags> typeFlags = new Dictionary<Type, TypeFlags>(new ByReferenceKeyComparer<Type>());
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;
}
}
}