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.
406 lines
14 KiB
406 lines
14 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Text; |
|
|
|
using ILRuntime.Runtime.Stack; |
|
|
|
namespace ILRuntime.Runtime |
|
{ |
|
public static class Extensions |
|
{ |
|
public static bool GetJITFlags(this Mono.Cecil.CustomAttribute attribute, Enviorment.AppDomain appdomain, out int flags) |
|
{ |
|
var at = appdomain.GetType(attribute.AttributeType, null, null); |
|
flags = ILRuntimeJITFlags.None; |
|
if (at == appdomain.JITAttributeType) |
|
{ |
|
if (attribute.HasConstructorArguments) |
|
{ |
|
flags = (int)attribute.ConstructorArguments[0].Value; |
|
} |
|
else |
|
flags = ILRuntimeJITFlags.JITOnDemand; |
|
return true; |
|
} |
|
else |
|
return false; |
|
} |
|
public static void GetClassName(this Type type, out string clsName, out string realClsName, out bool isByRef, bool simpleClassName = false) |
|
{ |
|
isByRef = type.IsByRef; |
|
int arrayRank = 1; |
|
|
|
if (isByRef) |
|
{ |
|
type = type.GetElementType(); |
|
} |
|
|
|
bool isArray = type.IsArray; |
|
|
|
if (isArray) |
|
{ |
|
arrayRank = type.GetArrayRank(); |
|
type = type.GetElementType(); |
|
if (type.IsArray) |
|
{ |
|
type.GetClassName(out clsName, out realClsName, out isByRef, simpleClassName); |
|
|
|
clsName += "_Array"; |
|
if (!simpleClassName) |
|
clsName += "_Binding"; |
|
if (arrayRank > 1) |
|
clsName += arrayRank; |
|
if (arrayRank <= 1) |
|
realClsName += "[]"; |
|
else |
|
{ |
|
StringBuilder sb = new StringBuilder(); |
|
sb.Append(realClsName); |
|
sb.Append('['); |
|
for (int i = 0; i < arrayRank - 1; i++) |
|
{ |
|
sb.Append(','); |
|
} |
|
sb.Append(']'); |
|
realClsName = sb.ToString(); |
|
} |
|
|
|
return; |
|
} |
|
} |
|
string realNamespace = null; |
|
bool isNestedGeneric = false; |
|
if (type.IsNested) |
|
{ |
|
string bClsName, bRealClsName; |
|
bool tmp; |
|
var rt = type.ReflectedType; |
|
if(rt.IsGenericType && rt.IsGenericTypeDefinition) |
|
{ |
|
if (type.IsGenericType) |
|
{ |
|
rt = rt.MakeGenericType(type.GetGenericArguments()); |
|
isNestedGeneric = true; |
|
} |
|
} |
|
GetClassName(rt, out bClsName, out bRealClsName, out tmp); |
|
clsName = bClsName + "_"; |
|
realNamespace = bRealClsName + "."; |
|
} |
|
else |
|
{ |
|
clsName = simpleClassName ? "" : (!string.IsNullOrEmpty(type.Namespace) ? type.Namespace.Replace(".", "_") + "_" : ""); |
|
|
|
if (string.IsNullOrEmpty(type.Namespace)) |
|
{ |
|
if (type.IsArray) |
|
{ |
|
var elementType = type.GetElementType(); |
|
if (elementType.IsNested && elementType.DeclaringType != null) |
|
{ |
|
realNamespace = elementType.Namespace + "." + elementType.DeclaringType.Name + "."; |
|
} |
|
else |
|
{ |
|
realNamespace = elementType.Namespace + "."; |
|
} |
|
} |
|
else |
|
{ |
|
realNamespace = "global::"; |
|
} |
|
} |
|
else |
|
{ |
|
realNamespace = type.Namespace + "."; |
|
} |
|
} |
|
clsName = clsName + type.Name.Replace(".", "_").Replace("`", "_").Replace("<", "_").Replace(">", "_"); |
|
bool isGeneric = false; |
|
string ga = null; |
|
if (type.IsGenericType && !isNestedGeneric) |
|
{ |
|
isGeneric = true; |
|
clsName += "_"; |
|
ga = "<"; |
|
var args = type.GetGenericArguments(); |
|
bool first = true; |
|
foreach (var j in args) |
|
{ |
|
if (first) |
|
first = false; |
|
else |
|
{ |
|
clsName += "_"; |
|
ga += ", "; |
|
} |
|
string a, b; |
|
bool tmp; |
|
GetClassName(j, out a, out b, out tmp, true); |
|
clsName += a; |
|
ga += b; |
|
} |
|
ga += ">"; |
|
} |
|
if (isArray) |
|
{ |
|
clsName += "_Array"; |
|
if (arrayRank > 1) |
|
clsName += arrayRank; |
|
} |
|
if (!simpleClassName) |
|
clsName += "_Binding"; |
|
|
|
realClsName = realNamespace; |
|
if (isGeneric) |
|
{ |
|
int idx = type.Name.IndexOf("`"); |
|
if (idx > 0) |
|
{ |
|
realClsName += type.Name.Substring(0, idx); |
|
realClsName += ga; |
|
} |
|
else |
|
realClsName += type.Name; |
|
} |
|
else |
|
realClsName += type.Name; |
|
|
|
if (isArray) |
|
{ |
|
if (arrayRank <= 1) |
|
realClsName += "[]"; |
|
else |
|
{ |
|
StringBuilder sb = new StringBuilder(); |
|
sb.Append(realClsName); |
|
sb.Append('['); |
|
for(int i=0;i<arrayRank - 1; i++) |
|
{ |
|
sb.Append(','); |
|
} |
|
sb.Append(']'); |
|
realClsName = sb.ToString(); |
|
} |
|
} |
|
|
|
} |
|
public static int ToInt32(this object obj) |
|
{ |
|
if (obj is int) |
|
return (int)obj; |
|
if (obj is float) |
|
return (int)(float)obj; |
|
if (obj is long) |
|
return (int)(long)obj; |
|
if (obj is short) |
|
return (int)(short)obj; |
|
if (obj is double) |
|
return (int)(double)obj; |
|
if (obj is byte) |
|
return (int)(byte)obj; |
|
if (obj is Intepreter.ILEnumTypeInstance) |
|
return (int)((Intepreter.ILEnumTypeInstance)obj)[0]; |
|
if (obj is uint) |
|
return (int)(uint)obj; |
|
if (obj is ushort) |
|
return (int)(ushort)obj; |
|
if (obj is sbyte) |
|
return (int)(sbyte)obj; |
|
return Convert.ToInt32(obj); |
|
} |
|
public static long ToInt64(this object obj) |
|
{ |
|
if (obj is long) |
|
return (long)obj; |
|
if (obj is int) |
|
return (long)(int)obj; |
|
if (obj is float) |
|
return (long)(float)obj; |
|
if (obj is short) |
|
return (long)(short)obj; |
|
if (obj is double) |
|
return (long)(double)obj; |
|
if (obj is byte) |
|
return (long)(byte)obj; |
|
if (obj is uint) |
|
return (long)(uint)obj; |
|
if (obj is ushort) |
|
return (long)(ushort)obj; |
|
if (obj is sbyte) |
|
return (long)(sbyte)obj; |
|
throw new InvalidCastException(); |
|
} |
|
public static short ToInt16(this object obj) |
|
{ |
|
if (obj is short) |
|
return (short)obj; |
|
if (obj is long) |
|
return (short)(long)obj; |
|
if (obj is int) |
|
return (short)(int)obj; |
|
if (obj is float) |
|
return (short)(float)obj; |
|
if (obj is double) |
|
return (short)(double)obj; |
|
if (obj is byte) |
|
return (short)(byte)obj; |
|
if (obj is uint) |
|
return (short)(uint)obj; |
|
if (obj is ushort) |
|
return (short)(ushort)obj; |
|
if (obj is sbyte) |
|
return (short)(sbyte)obj; |
|
throw new InvalidCastException(); |
|
} |
|
public static float ToFloat(this object obj) |
|
{ |
|
if (obj is float) |
|
return (float)obj; |
|
if (obj is int) |
|
return (float)(int)obj; |
|
if (obj is long) |
|
return (float)(long)obj; |
|
if (obj is short) |
|
return (float)(short)obj; |
|
if (obj is double) |
|
return (float)(double)obj; |
|
if (obj is byte) |
|
return (float)(byte)obj; |
|
if (obj is uint) |
|
return (float)(uint)obj; |
|
if (obj is ushort) |
|
return (float)(ushort)obj; |
|
if (obj is sbyte) |
|
return (float)(sbyte)obj; |
|
throw new InvalidCastException(); |
|
} |
|
|
|
public static double ToDouble(this object obj) |
|
{ |
|
if (obj is double) |
|
return (double)obj; |
|
if (obj is float) |
|
return (float)obj; |
|
if (obj is int) |
|
return (double)(int)obj; |
|
if (obj is long) |
|
return (double)(long)obj; |
|
if (obj is short) |
|
return (double)(short)obj; |
|
if (obj is byte) |
|
return (double)(byte)obj; |
|
if (obj is uint) |
|
return (double)(uint)obj; |
|
if (obj is ushort) |
|
return (double)(ushort)obj; |
|
if (obj is sbyte) |
|
return (double)(sbyte)obj; |
|
throw new InvalidCastException(); |
|
} |
|
|
|
public static Type GetActualType(this object value) |
|
{ |
|
if (value is ILRuntime.Runtime.Enviorment.CrossBindingAdaptorType) |
|
return ((ILRuntime.Runtime.Enviorment.CrossBindingAdaptorType)value).ILInstance.Type.ReflectionType; |
|
if (value is ILRuntime.Runtime.Intepreter.ILTypeInstance) |
|
return ((ILRuntime.Runtime.Intepreter.ILTypeInstance)value).Type.ReflectionType; |
|
else |
|
return value.GetType(); |
|
} |
|
|
|
public static bool MatchGenericParameters(this System.Reflection.MethodInfo m, Type[] genericArguments, Type returnType, params Type[] parameters) |
|
{ |
|
var param = m.GetParameters(); |
|
if (param.Length == parameters.Length) |
|
{ |
|
var args = m.GetGenericArguments(); |
|
if (args.Length != genericArguments.Length) |
|
{ |
|
return false; |
|
} |
|
if (args.MatchGenericParameters(m.ReturnType, returnType, genericArguments)) |
|
{ |
|
for (int i = 0; i < param.Length; i++) |
|
{ |
|
if (!args.MatchGenericParameters(param[i].ParameterType, parameters[i], genericArguments)) |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
else |
|
return false; |
|
} |
|
else |
|
return false; |
|
} |
|
|
|
public static bool MatchGenericParameters(this Type[] args, Type type, Type q, Type[] genericArguments) |
|
{ |
|
if (type.IsGenericParameter) |
|
{ |
|
for (int i = 0; i < args.Length; i++) |
|
{ |
|
if (args[i] == type) |
|
{ |
|
return q == genericArguments[i]; |
|
} |
|
} |
|
throw new NotSupportedException(); |
|
} |
|
else |
|
{ |
|
if (type.IsArray) |
|
{ |
|
if (q.IsArray) |
|
{ |
|
return MatchGenericParameters(args, type.GetElementType(), q.GetElementType(), genericArguments); |
|
} |
|
else |
|
return false; |
|
} |
|
else if (type.IsByRef) |
|
{ |
|
if (q.IsByRef) |
|
{ |
|
return MatchGenericParameters(args, type.GetElementType(), q.GetElementType(), genericArguments); |
|
} |
|
else |
|
return false; |
|
} |
|
else if (type.IsGenericType) |
|
{ |
|
if (q.IsGenericType) |
|
{ |
|
var t1 = type.GetGenericTypeDefinition(); |
|
var t2 = type.GetGenericTypeDefinition(); |
|
if (t1 == t2) |
|
{ |
|
var argA = type.GetGenericArguments(); |
|
var argB = q.GetGenericArguments(); |
|
if (argA.Length == argB.Length) |
|
{ |
|
for (int i = 0; i < argA.Length; i++) |
|
{ |
|
if (!MatchGenericParameters(args, argA[i], argB[i], genericArguments)) |
|
return false; |
|
} |
|
return true; |
|
} |
|
else |
|
return false; |
|
} |
|
else |
|
return false; |
|
} |
|
else |
|
return false; |
|
} |
|
else |
|
return type == q; |
|
} |
|
} |
|
} |
|
}
|
|
|