예제 #1
0
 static CloneHelper()
 {
     FuncMemberwiseClone = MethodHelper.CreateDelegate <Func <object, object> >(
         typeof(object).GetMethod(nameof(MemberwiseClone), BindingFlags.NonPublic | BindingFlags.Instance),
         false);
 }
예제 #2
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);
        }
예제 #3
0
 static CloneHelper()
 {
     FuncMemberwiseClone = MethodHelper.CreateDelegate <Func <object, object> >(
         typeof(object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance),
         SignatureLevels.Cast);
 }
예제 #4
0
파일: TypeHelper.cs 프로젝트: zxbe/Swifter
        private static object AllocateByInternal(Type type)
        {
            if (!allocateIsInitialized)
            {
                lock (typeof(TypeHelper))
                {
                    if (!allocateIsInitialized)
                    {
                        allocateIsInitialized = true;

                        var allocateMethod = typeof(RuntimeTypeHandle).GetMethod(AllocateMethodName, BindingFlags.NonPublic | BindingFlags.Static);
                        if (allocateMethod != null)
                        {
                            allocate = MethodHelper.CreateDelegate <AllocateDelegate>(allocateMethod, SignatureLevels.Cast);
                        }

                        var stubHelpersType = Type.GetType(StubHelpersTypeName);
                        if (stubHelpersType != null)
                        {
                            var allocateInternalMethod = stubHelpersType.GetMethod(AllocateInternalName, BindingFlags.Static | BindingFlags.NonPublic);
                            if (allocateInternalMethod != null)
                            {
                                allocateInternal = MethodHelper.CreateDelegate <AllocateInternalDelegate>(allocateInternalMethod, SignatureLevels.Cast);
                            }
                        }

                        var activationServicesType = Type.GetType(ActivationServicesTypeName);
                        if (activationServicesType != null)
                        {
                            var allocateUninitializedClassInstanceMethod = activationServicesType.GetMethod(AllocateUninitializedClassInstanceName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
                            if (allocateUninitializedClassInstanceMethod != null)
                            {
                                allocateUninitializedClassInstance = MethodHelper.CreateDelegate <AllocateUninitializedClassInstanceDelegate>(allocateUninitializedClassInstanceMethod, SignatureLevels.Cast);
                            }
                        }
                    }
                }
            }

            if (allocate != null)
            {
                try
                {
                    return(allocate(type));
                }
                catch (Exception)
                {
                }
            }

            if (allocateInternal != null)
            {
                try
                {
                    return(allocateInternal(type.TypeHandle.Value));
                }
                catch (Exception)
                {
                }
            }

            if (allocateUninitializedClassInstance != null)
            {
                try
                {
                    return(allocateUninitializedClassInstance(type));
                }
                catch (Exception)
                {
                }
            }

            return(null);
        }