using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace Common
{
    public sealed class StructConverter
    {
        private static log4net.ILog logger = log4net.LogManager.GetLogger(typeof(StructConverter));

        public static int SizeOf(object structObj)
        {
            unsafe { return Marshal.SizeOf(structObj); }
        }

        public static int SizeOf(Type type)
        {
            return Marshal.SizeOf(type);
        }

        public static int SizeOf<T>()
        {
            return Marshal.SizeOf(typeof(T));
        }

        /// <summary>
        /// 结构体转成字节数组
        /// </summary>
        /// <param name="structObj"></param>
        /// <returns></returns>
        public static byte[] StructToBytes(object structObj)
        {
            int size = SizeOf(structObj);
            byte[] bytes = new byte[size];
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            try
            {
                Marshal.StructureToPtr(structObj, structPtr, false);
                Marshal.Copy(structPtr, bytes, 0, size);
            }
            finally
            {
                Marshal.FreeHGlobal(structPtr);
            }
            return bytes;
        }
        /// <summary>
        /// 字节数组转成结构体
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object BytesToStruct(byte[] bytes, Type type)
        {
            return BytesToStruct(bytes, 0, type);
        }
        /// <summary>
        /// 字节数组转成结构体
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="startIndex"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object BytesToStruct(byte[] bytes, int startIndex, Type type)
        {
            object structObj = null;
            int size = Marshal.SizeOf(type);
            if (startIndex < 0 || startIndex >= bytes.Length || size > bytes.Length)
            {
                return null;
            }
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            try
            {
                Marshal.Copy(bytes, startIndex, structPtr, size);
                structObj = Marshal.PtrToStructure(structPtr, type);
            }
            catch (Exception ex)
            {
            }
            finally
            {
                Marshal.FreeHGlobal(structPtr);
            }
            return structObj;
        }
    }
}
