using Microsoft.CSharp; using System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Security.Cryptography; using System.Text; using UnityEngine; namespace XGame { public class Type_Null { public static int Reserve = 0; } public static partial class Utility { //private static float FLOAT_PRECISION = 1e-5f; private static Dictionary sActorIdDic = new Dictionary(); private static Dictionary sTypeDic = new Dictionary(); private static Dictionary Asms = new Dictionary(); private static Type typeNull = typeof(Type_Null); public static int GenClientNameId(string actorTypeName) { if (sActorIdDic.ContainsKey(actorTypeName) == false) { sActorIdDic.Add(actorTypeName, 0); } ++sActorIdDic[actorTypeName]; return sActorIdDic[actorTypeName]; } static Type SuperGetType(string sTypeName) { Type typeValue; if (sTypeDic.TryGetValue(sTypeName, out typeValue)) { if (typeValue == typeNull) return null; else return typeValue; } else { typeValue = Type.GetType(sTypeName);//底包的类型有就不用下面的麻烦代码 if (typeValue != null) { sTypeDic[sTypeName] = typeValue; //Debug.Log($"SuperGetType sTypeDic 1 : {sTypeName}"); return typeValue; } Assembly[] foundAsms = null; if (Asms.Count == 0) { foundAsms = AppDomain.CurrentDomain.GetAssemblies(); foreach (var asm in foundAsms) { //只检查GYFramework 和Assembly-CSharp 热更相关的dll //Debug.Log($"SuperGetType : {sTypeName} ({asm.GetName().Name})"); string asmName = asm.GetName().Name; if (asmName == "GYFramework" || asmName == "Assembly-CSharp") { Asms[asmName] = asm; } } } foreach (var asm in Asms) { typeValue = asm.Value.GetType(sTypeName); if (typeValue != null) { sTypeDic[sTypeName] = typeValue; //Debug.Log($"SuperGetType sTypeDic 2 : {sTypeName}"); return typeValue; } } //最后全量查找 if (null == foundAsms) { foundAsms = AppDomain.CurrentDomain.GetAssemblies(); } foreach (var asm in foundAsms) { string asmName = asm.GetName().Name; typeValue = asm.GetType(sTypeName); if (typeValue != null) { Asms[asmName] = asm; sTypeDic[sTypeName] = typeValue; //Debug.Log($"SuperGetType sTypeDic 3: {sTypeName}"); return typeValue; } } sTypeDic[sTypeName] = typeNull; //Debug.Log($"SuperGetType Error : {sTypeName} == null"); } return null; } public static Type GetTypeByTypeName(string typeName) { System.Type type = SuperGetType(typeName);//Type.GetType(typeName);// if (null == type) { string newTypeName = "XGame" + "." + typeName; type = SuperGetType(newTypeName); //Type.GetType(newTypeName);// //if (null == type) //{ // newTypeName = "XGame" + "." + typeName; // type = SuperGetType(newTypeName); //Type.GetType(newTypeName);// //} } return type; } public static Type GetTypeByTypeName(string typeName) where BaseType : class { System.Type type = Type.GetType(typeName); if (type == null) { string newTypeName = "XGame" + "." + typeName; type = Type.GetType(newTypeName); //if (type == null) //{ // newTypeName = "XGame" + "." + typeName; // type = Type.GetType(newTypeName); //} } if (type == null) { Debug.LogError("GetTypeByTypeName typeName:{0} get type return null"); return null; } if (!typeof(BaseType).IsAssignableFrom(type)) { Debug.LogError($"GetTypeByTypeName typeName:{typeName} is not subclass of {typeof(BaseType).FullName}"); return null; } return type; } /// /// 判断指定的类型 是否是指定泛型类型的子类型,或实现了指定泛型接口。 /// /// 需要测试的类型。 /// 泛型接口类型,传入 typeof(IXxx) /// 如果是泛型接口的子类型,则返回 true,否则返回 false。 public static bool HasImplementedRawGeneric(this Type type, Type generic) { if (type == null) throw new ArgumentNullException(nameof(type)); if (generic == null) throw new ArgumentNullException(nameof(generic)); // 测试接口。 var isTheRawGenericType = type.GetInterfaces().Any(IsTheRawGenericType); if (isTheRawGenericType) return true; // 测试类型。 while (type != null && type != typeof(object)) { isTheRawGenericType = IsTheRawGenericType(type); if (isTheRawGenericType) return true; type = type.BaseType; } // 没有找到任何匹配的接口或类型。 return false; // 测试某个类型是否是指定的原始接口。 bool IsTheRawGenericType(Type test) => generic == (test.IsGenericType ? test.GetGenericTypeDefinition() : test); } public static object GetPropValue(object obj, String name) { foreach (String part in name.Split('.')) { if (obj == null) { return null; } Type type = obj.GetType(); PropertyInfo info = type.GetProperty(part); if (info == null) { return null; } obj = info.GetValue(obj, null); } return obj; } public static T GetPropValue(object obj, String name) { object retval = GetPropValue(obj, name); if (retval == null) { return default(T); } // throws InvalidCastException if types are incompatible return (T)retval; } public static object GetFieldValue(object obj, String name) { foreach (String part in name.Split('.')) { if (obj == null) { return null; } Type type = obj.GetType(); FieldInfo info = type.GetField(part); if (info == null) { return null; } obj = info.GetValue(obj); } return obj; } public static T GetFieldValue(object obj, String name) { object retval = GetFieldValue(obj, name); if (retval == null) { return default(T); } // throws InvalidCastException if types are incompatible return (T)retval; } public static T CreateInstance(string typeName, params object[] args) where T : class { if (string.IsNullOrEmpty(typeName) || typeName == "") { typeName = typeof(T).FullName; } Type type = Type.GetType(typeName); if (type == null) { Debug.LogError($"Get Type from type name:{type} return null"); return null; } if (typeof(T).IsAssignableFrom(type) == false) { Debug.LogError($"{type} is not assignable from {typeof(T).Name}"); return null; } T instance = Activator.CreateInstance(type, args) as T; return instance; } public static object CopyObject(object srcObject) { Type type = srcObject.GetType(); object newObject = Activator.CreateInstance(type); FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); for (int i = 0; i < fields.Length; ++i) { FieldInfo fi = fields[i]; fi.SetValue(newObject, fi.GetValue(srcObject)); } PropertyInfo[] props = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); for (int i = 0; i < props.Length; ++i) { PropertyInfo fi = props[i]; fi.SetValue(newObject, fi.GetValue(srcObject)); } return newObject; } public static bool CopyObject(object srcObject, object targetObject) { Type srcType = srcObject.GetType(); Type targetType = targetObject.GetType(); if (srcType != targetType) { return false; } FieldInfo[] fields = srcType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); for (int i = 0; i < fields.Length; ++i) { FieldInfo fi = fields[i]; fi.SetValue(targetObject, fi.GetValue(srcObject)); } PropertyInfo[] props = srcType.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); for (int i = 0; i < props.Length; ++i) { PropertyInfo fi = props[i]; fi.SetValue(targetObject, fi.GetValue(srcObject)); } return true; } public static object CopyFields(object src) { Type t = src.GetType(); object res = Activator.CreateInstance(t); FieldInfo[] list = t.GetFields(); for (int i = 0; i < list.Length; ++i) { FieldInfo fi = list[i]; fi.SetValue(res, fi.GetValue(src)); } return res; } public static T ParseEnum(string value, T defaultValue) where T : struct { T v; return Enum.TryParse(value, true, out v) ? v : defaultValue; } public static void ThrowError(string fmt, params object[] args) { string msg = String.Format(fmt, args); throw new Exception(msg); } /// /// 计算字符串的MD5值 /// public static string GetStringMd5(string source) { MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); byte[] data = System.Text.Encoding.UTF8.GetBytes(source); byte[] md5Data = md5.ComputeHash(data, 0, data.Length); md5.Clear(); string destString = ""; for (int i = 0; i < md5Data.Length; i++) { destString += System.Convert.ToString(md5Data[i], 16).PadLeft(2, '0'); } destString = destString.PadLeft(32, '0'); return destString.ToUpper(); } /// /// 计算文件的MD5值 /// public static string GetFileMd5(string file) { try { FileStream fs = new FileStream(file, FileMode.Open); System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); byte[] retVal = md5.ComputeHash(fs); fs.Close(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < retVal.Length; i++) { sb.Append(retVal[i].ToString("x2")); } return sb.ToString(); } catch (Exception ex) { throw new Exception("md5file() fail, error:" + ex.Message); } } public static string GetBytesMd5(byte[] bytes) { System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); byte[] retVal = md5.ComputeHash(bytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < retVal.Length; i++) { sb.Append(retVal[i].ToString("x2")); } return sb.ToString(); } public static long GetTimeTick() { var ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalMilliseconds); } public static double XWorldGetTime() { return Time.realtimeSinceStartupAsDouble; } public static bool IsPossibleSimulator() { if (Application.isEditor) { return false; } bool isSimulator = false; isSimulator = isSimulator || SystemInfo.graphicsDeviceName == "Netease"; isSimulator = isSimulator || SystemInfo.deviceModel == "Netease MuMu"; string processorType = SystemInfo.processorType.ToLower(); isSimulator = isSimulator || processorType.Contains("intel") || processorType.Contains("amd"); return isSimulator; } // 格式化文件大小 private static string[] sSuffix = { "B", "KB", "MB", "GB", "TB" }; public static string FormatBytesStr(long bytes) { float size = Convert.ToSingle(bytes); int sufIdx = 0; for(sufIdx = 0; sufIdx < sSuffix.Length; sufIdx++) { if(size >= 1024) { size = Mathf.Ceil(size / 1024); continue; } else { break; } } string format = size + sSuffix[sufIdx]; return format; } public static bool Contains(T[] array, T value) where T : class { for (int i = 0; i < array.Length; ++i) { if (array[i] == value) { return true; } } return false; } public static bool Contains(string[] array, string value) { for (int i = 0; i < array.Length; ++i) { if (array[i].CompareTo(value) == 0) { return true; } } return false; } public static int RandomRangeToInt(int min,int max) { return UnityEngine.Random.Range(min,max); } public static void CreateMulDirectory(string path) { if (Directory.Exists(path)) return; int n = path.LastIndexOf('/'); if(n == -1) n = path.LastIndexOf('\\'); if (n == -1) { Directory.CreateDirectory(path); return; } string subpath = path.Substring(0, n); if (Directory.Exists(subpath)) { Directory.CreateDirectory(path); } else { CreateMulDirectory(subpath); Directory.CreateDirectory(path); } } } }