Exemplo n.º 1
0
        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]);
            }
        }
Exemplo n.º 2
0
        /// <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));
        }
Exemplo n.º 3
0
        /// <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));
        }
Exemplo n.º 4
0
        /// <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);
        }