通过反射将对象转化为文件,同时反向将文件还原为对象(适用配置文件读写)

文件和对象的转换

在写程序中经常会使用到配置文件,而且配置文件的内容通常还是要赋值给对象,那么每次如果都给一个特定的类去写一套读写肯定是很不方便,由于工作上的需求所以顺便写了一个通用的只要提供对象即可(ps:要保存的内容只能是基础类型,如果对象中有引用类型的将不会被保存,不过大部分配置文件的内容应该都是基础类型就OK了)
    /// <summary>
    /// 把对象转化为文件的内容
    /// </summary>
    public static class StreamClassToFile
    {
        /// <summary>
        /// 每个对象的分隔
        /// </summary>
        private static string ClassLog = "`------------------------`" + RowEndLog;
        /// <summary>
        /// 单个对象的标志
        /// </summary>
        private static string SingleHandLog = "Single\n";
        /// <summary>
        /// 多个对象的标志
        /// </summary>
        private static string MoreleHandLog = "More\n";
        /// <summary>
        /// 分隔符
        /// </summary>
        private static string CenterLog = "|~|";
        /// <summary>
        /// 行结尾符
        /// </summary>
        private static string RowEndLog = "\n";
        /// <summary>
        /// 字段开始标识
        /// </summary>
        private static string FieldStartLog = "<|Fields>";
        /// <summary>
        /// 字段结束标识
        /// </summary>
        private static string FieldEndLog = "<Fields|>";
        /// <summary>
        /// 开始对象标识
        /// </summary>
        private static string ObjectStartLog = "<|Object>";
        /// <summary>
        /// 结束对象标识
        /// </summary>
        private static string ObjectEndLog = "<Object|>";
        /// <summary>
        /// 将对象保存到文件
        /// </summary>
        /// <param name="obj"></param>
        public static void ObjectToFile(object obj, string fileName)
        {
            string saveString = SingleHandLog;
            saveString += ObjectToString(obj);
            using (Stream stream = new FileStream(fileName, FileMode.Create))
            {
                byte[] data = Encoding.UTF8.GetBytes(saveString);
                stream.Write(data, 0, data.Length);
            }
        }
        /// <summary>
        /// 将对象转换为字符串
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private static string ObjectToString(object obj)
        {
            StringBuilder saveString = new StringBuilder();
            Type type = obj.GetType();
            saveString.Append(ObjectStartLog);
            saveString.Append(type.Name + RowEndLog);
            FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
            ///存储字段
            saveString.Append(FieldStartLog + RowEndLog);
            foreach (var item in fields)
            {
                if (IsBasisType(item.FieldType))
                    saveString.Append(item.FieldType.Name + CenterLog + item.Name + CenterLog + item.GetValue(obj).ToString() + CenterLog + RowEndLog);
            }
            saveString.Append(FieldEndLog + RowEndLog);
            saveString.Append(ObjectEndLog);
            return saveString.ToString();
        }
        /// <summary>
        /// 将文件中的数据读取并且还原为一个对象(只支持有空构造函数的对象)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static T FileToObject<T>(string fileName)
        {
            StringBuilder readString = new StringBuilder();
            using (StreamReader stream = new StreamReader(fileName, Encoding.UTF8))
            {
                readString.Append(stream.ReadToEnd());
            }
            int logindex = readString.ToString().IndexOf(SingleHandLog);
            if (logindex == -1 || logindex > SingleHandLog.Length)
            {
                return default(T);
            }
            return GetObjectByString<T>(readString.ToString());
        }
        /// <summary>
        /// 根据类字符串组装类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="readString"></param>
        /// <returns></returns>
        private static T GetObjectByString<T>(string readString)
        {
            try
            { 
                Type type = typeof(T);
                //type.GetConstructor( BindingFlags.Public, new );
                object readobj = Activator.CreateInstance(type);

                FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
                ListData fieldsData = GetFieldValue(readString);///解析所有字段获取值

                foreach (var item in fields)
                {
                    if (IsBasisType(item.FieldType))
                    {
                        item.SetValue(readobj, GetValue(fieldsData[item.Name], item));
                    }
                }
                return (T)readobj;
            }
            catch (Exception ex)
            {
                return default(T);
            }
        }
        /// <summary>
        /// 检测是否是基础类型,只支持基础类型
        /// </summary>
        /// <param name="typeName">类型名</param>
        /// <returns>true为是,false为否</returns>
        public static bool IsBasisType(Type type)
        {
            if (type.IsPrimitive || type.Name == "string" || type.Name == "String" || type.Name == "Guid")
                return true;
            else
                return false;
        }
        /// <summary>
        /// 获取获取字段的数据
        /// </summary>
        /// <param name="info">字段信息</param>
        /// <param name="file">总文件流</param>
        /// <returns></returns>
        private static ListData GetFieldValue(string file)
        {
            ListData data = new ListData();
            string fieldstring = file.ToString();
            int startIndex = fieldstring.IndexOf(FieldStartLog);
            int endIndex = fieldstring.IndexOf(FieldEndLog);
            fieldstring = fieldstring.Substring((startIndex + FieldStartLog.Length), (endIndex - startIndex - FieldStartLog.Length));
            string[] fields = fieldstring.Split(RowEndLog.ToCharArray());
            string[] values;
            foreach (var item in fields)
            {
                values = item.Split(CenterLog.ToCharArray());
                if (values.Length <= 1)
                    continue;
                data.Add(values[CenterLog.Length], values[CenterLog.Length * 2]);
            }
            return data;
        }
        /// <summary>
        /// 根据字段的类型变成对应的字段的值
        /// </summary>
        /// <param name="value">字段的值的字符串</param>
        /// <param name="type">字段的类型</param>
        /// <returns></returns>
        private static object GetValue(string value, FieldInfo type)
        {
            try
            {
                TypeCode code = GetEnumTypeByString<TypeCode>(type.FieldType.Name);
                if (code == TypeCode.Empty && type.FieldType.Name == "Guid")
                    return new Guid(value);
                return Convert.ChangeType(value, code);
            }
            catch(Exception ex)
            {
                if(type.Name == "string")
                {
                    return value;
                }
                else
                {
                    return null;
                }
            }
        }
        /// <summary>
        /// 批量读取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="objs"></param>
        /// <param name="fileName"></param>
        public static List<T> FileToObjects<T>( string fileName)
        {
            StringBuilder readString = new StringBuilder();
            using (StreamReader stream = new StreamReader(fileName, Encoding.UTF8))
            {
                readString.Append(stream.ReadToEnd());
            }
            int logindex = readString.ToString().IndexOf(MoreleHandLog);
            if (logindex == -1 || logindex > MoreleHandLog.Length)
            {
                return default(List<T>);
            }
            List<T> objs = new List<T>();
            ////string[] classtrings = readString.ToString().Split(ClassLog.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            string[] classtrings = Regex.Split(readString.ToString(), ClassLog);
            int index = 0;
            foreach (string item in classtrings)
            {
                //if(index ++ % ClassLog.Length ==0 && index != classtrings.Length)
                if(item.Length != 0)
                    objs.Add(GetObjectByString<T>(item));
            }
            return objs;
        }
        /// <summary>
        /// 将多个对象保存到文件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="objs"></param>
        /// <param name="fileName"></param>
        public static void ObjectsToFile<T>(List<T> objs, string fileName)
        {
            StringBuilder saveStrings = new StringBuilder();
            saveStrings.Append(MoreleHandLog);
            foreach (object item in objs)
            {
                saveStrings.Append(ObjectToString(item));
                saveStrings.Append(ClassLog);
            }
            using (Stream stream = new FileStream(fileName, FileMode.Create))
            {
                byte[] data = Encoding.UTF8.GetBytes(saveStrings.ToString());
                stream.Write(data, 0, data.Length);
            }
        }
        /// <summary>
        /// 根据name检索对应枚举
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <returns></returns>
        public static T GetEnumTypeByString<T>(string name)
        {
            foreach (T item in Enum.GetValues(typeof(T)))
            {
                if(item.ToString() == name)
                {
                    return item;
                }
            }
            return default(T);
        }
        /// <summary>
        /// 线性插值
        /// </summary>
        /// <param name="start">起始值</param>
        /// <param name="end">终止值</param>
        /// <param name="lerp">插值</param>
        /// <returns></returns>
        public static double Lerp(double start, double end, double lerp)
        {
            lerp = lerp < 0 ? 0 : lerp;
            lerp = lerp > 1 ? 1 : lerp;
            return (end + start) * lerp;
        } 
        /// <summary>
        /// 根据T类型的枚举的具体V类型的值获取对应的枚举值
        /// </summary>
        /// <typeparam name="T">枚举类型</typeparam>
        /// <typeparam name="V">枚举类型继承的类型</typeparam>
        /// <param name="value">对应的值</param>
        /// <returns>对应的枚举值</returns>
        public static T GetEnumTypeByType<T, V>(V value)
        {
            try
            {
                TypeCode code = GetEnumTypeByString<TypeCode>(value.GetType().Name);
                foreach (T item in Enum.GetValues(typeof(T)))
                {
                    if (Convert.ChangeType(value, code).Equals(value))
                    {
                        return item;
                    }
                }
                return default(T);
            }
            catch (Exception)
            {
                return default(T);
            }

        }
    }

    internal class ListData
    {
        /// <summary>
        /// 数据
        /// </summary>
        private Dictionary<string, string> _data = new Dictionary<string, string>();
        /// <summary>
        /// 根据名称获取值
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public string this[string name]
        {
            get
            {
                if(_data.Keys.Contains(name))
                {
                    return _data[name];
                }
                return "";
            }
        }
        /// <summary>
        /// 数据
        /// </summary>
        public Dictionary<string, string> Data
        {
            get
            {
                return _data;
            }
        }
        /// <summary>
        /// 添加一条数据
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="value">属性的值</param>
        public void Add(string name, string value)
        {
            _data.Add(name, value);
        }
    }
使用的时候只要调用StreamClassToFile.ObjectToFile(对象, 文件名称包含路径和名称);
同时还有ObjectsToFile支持List<T>类型的转化。
反向的是public static T FileToObject<T>(string fileName)
同样支持返回List<T>的对象组
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值