private static uint OffsetOfByDynamic(FieldInfo fieldInfo) { if (fieldOffsetCache == null) { lock (lockObject) { if (fieldOffsetCache == null) { fieldOffsetCache = new IdCache <uint>(); fieldOffsetCacheLock = new object(); } } } var fieldId = (long)fieldInfo.FieldHandle.Value; if (fieldOffsetCache.TryGetValue(fieldId, out uint offset)) { return(offset); } lock (fieldOffsetCacheLock) { if (fieldOffsetCache.TryGetValue(fieldId, out offset)) { return(offset); } GetAllFieldOffsetByDynamic(fieldInfo.DeclaringType); return(fieldOffsetCache[fieldId]); } }
/// <summary> /// 转换方法。 /// </summary> /// <param name="obj">值</param> /// <returns>返回新值</returns> public static TDestination Convert(object obj) { if (obj == null) { return(XConvert <object, TDestination> .Convert(null)); } if (obj is TDestination) { return((TDestination)obj); } var typeKey = (long)Pointer.GetTypeHandle(obj); IDConvert <TDestination> value; if (!Cache.TryGetValue(typeKey, out value)) { lock (CacheLock) { if (!Cache.TryGetValue(typeKey, out value)) { var type = typeof(XConvert <,>).MakeGenericType(obj.GetType(), typeof(TDestination)); value = (IDConvert <TDestination>)Activator.CreateInstance(type); Cache.Add(typeKey, value); } } } return(value.Convert(obj)); }
/// <summary> /// 转换方法。 /// </summary> /// <param name="source">值</param> /// <param name="type">目标类型</param> /// <returns>返回新值</returns> public static object Convert(TSource source, Type type) { var typeKey = type.TypeHandle.Value.ToInt64(); ISConvert <TSource> value; if (!Cache.TryGetValue(typeKey, out value)) { lock (CacheLock) { if (!Cache.TryGetValue(typeKey, out value)) { var convertType = typeof(XConvert <,>).MakeGenericType(typeof(TSource), type); value = (ISConvert <TSource>)Activator.CreateInstance(convertType); Cache.Add(typeKey, value); } } } return(value.Convert(source)); }
/// <summary> /// 获取一个类型占用的内存大小。如果是 Class 则不包括 ObjectHandle 的大小。 /// </summary> /// <param name="type">类型信息</param> /// <returns>返回内存大小。</returns> public unsafe static uint SizeOf(Type type) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (type is TypeBuilder) { throw new ArgumentException("Unable get size of a TypeBuilder.", nameof(type)); } if (type.IsGenericTypeDefinition) { throw new ArgumentException("Unable get size of a generic definition type.", nameof(type)); } if (type.IsGenericTypeDefinition) { return(0); } switch (Type.GetTypeCode(type)) { case TypeCode.Boolean: return(sizeof(bool)); case TypeCode.Char: return(sizeof(char)); case TypeCode.SByte: return(sizeof(sbyte)); case TypeCode.Byte: return(sizeof(byte)); case TypeCode.Int16: return(sizeof(short)); case TypeCode.UInt16: return(sizeof(ushort)); case TypeCode.Int32: return(sizeof(int)); case TypeCode.UInt32: return(sizeof(uint)); case TypeCode.Int64: return(sizeof(long)); case TypeCode.UInt64: return(sizeof(ulong)); case TypeCode.Single: return(sizeof(float)); case TypeCode.Double: return(sizeof(double)); case TypeCode.Decimal: return(sizeof(decimal)); case TypeCode.DateTime: return((uint)sizeof(DateTime)); } if (type.IsPointer || type.IsInterface || type.IsByRef || typeof(object) == type || typeof(IntPtr) == type) { return((uint)IntPtr.Size); } if (typeSizeCache == null) { lock (lockObject) { if (typeSizeCache == null) { typeSizeCache = new IdCache <uint>(); typeSizeCacheLock = new object(); } var sizeOfHelperMethod = typeof(Marshal).GetMethod(MarshalSizeOfHelperName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); if (sizeOfHelperMethod != null) { sizeOfHelper = MethodHelper.CreateDelegate <SizeOfHelperDelegate>(sizeOfHelperMethod, SignatureLevels.Cast); } pointerSizeOfMethod = typeof(Pointer).GetMethod(nameof(Pointer.SizeOf), Type.EmptyTypes); } } if (type.IsValueType) { if (sizeOfHelper != null) { return((uint)sizeOfHelper(type, false)); } try { return((uint)Marshal.SizeOf(type)); } catch (Exception) { } } var typeId = (long)type.TypeHandle.Value; if (typeSizeCache.TryGetValue(typeId, out uint size)) { return(size); } lock (typeSizeCacheLock) { if (typeSizeCache.TryGetValue(typeId, out size)) { return(size); } if (type.IsValueType) { size = (uint)pointerSizeOfMethod.MakeGenericMethod(type).Invoke(null, null); } else { var fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); if (fields.Length == 0) { size = (uint)IntPtr.Size; } else { int right = fields.Length - 1; var maxOffset = OffsetOf(fields[right]); var maxOffsetFieldType = fields[right].FieldType; while (right > 0) { --right; var offset = OffsetOf(fields[right]); if (offset > maxOffset) { maxOffset = offset; maxOffsetFieldType = fields[right].FieldType; } } // = last field offset + last field size + type handle size; size = maxOffset + (maxOffsetFieldType.IsValueType ? SizeOf(maxOffsetFieldType) : (uint)IntPtr.Size) + ((uint)IntPtr.Size); } } typeSizeCache[typeId] = size; } return(size); }