using Common.Models; using Microsoft.Win32; using Newtonsoft; using Newtonsoft.Json; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Windows; using System.Windows.Media; using System.Xml.Serialization; namespace Common { public class File_Operator { private static readonly object _lock = new object(); public static T Xml_Serialize(string strFile, bool bSave, T param, out bool bReadOK) where T : class { lock (_lock) { bReadOK = true; XmlSerializer xs = null; // 针对 BaseBottleBox 集合,显式指定所有派生类 if (typeof(T) == typeof(ProjectProperty)) { Type[] extraTypes = new Type[] { typeof(BaseBottleBox), typeof(SampleBottleBoxModel), typeof(SourceLiquidBottleBoxModel), typeof(SourcePowderBottleBoxModel), typeof(SourcePowderBottleBoxModel_125ml), typeof(TipBoxModel), typeof(SourcePowderBottleModel), typeof(TipHeadItem) }; xs = new XmlSerializer(typeof(ProjectProperty), extraTypes); } else { xs = new XmlSerializer(param.GetType()); } try { // 使用 using 自动释放流(避免资源泄漏) if (bSave) { using (Stream stream = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read)) { xs.Serialize(stream, param); } } else { if (File.Exists(strFile)) { using (Stream stream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.Read)) { param = xs.Deserialize(stream) as T; } return param; } else { // 文件不存在时,先创建并序列化默认值 using (Stream stream = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read)) { xs.Serialize(stream, param); } // 重新读取 using (Stream stream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.Read)) { param = xs.Deserialize(stream) as T; } return param; } } } catch (Exception ex) { bReadOK = false; MessageBox.Show($"序列化失败:{ex.Message}\n{ex.StackTrace}", "错误"); } return null; } } /// /// XML文件读写 /// 保存配置参数 bReadOK==false为发生异常 /// /// 类类型 /// 完整文件路径名 /// true:保存;false:读取 /// 要进行序列化或反序列化的对象实例 /// 是否读写成功,有异常 /// 读取的数据 //public static T Xml_Serialize(string strFile, bool bSave, T param, out bool bReadOK) where T : class //{ // lock (_lock) // { // bReadOK = true; // XmlSerializer xs = new XmlSerializer(param.GetType()); // try // { // if (bSave) // { // //创建一个 FileStream 对象,以 FileMode.Create 模式打开文件,用于写入数据。 // //使用 xs.Serialize 方法将 param 对象序列化为 XML 数据,并写入文件。 // //关闭文件流。 // Stream stream = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read); // xs.Serialize(stream, param); // stream.Close(); // } // else // { // //检查文件是否存在。 // //如果文件存在,创建一个 FileStream 对象,以 FileMode.Open 模式打开文件,用于读取数据。 // //使用 xs.Deserialize 方法将文件中的 XML 数据反序列化为 T 类型的对象,并赋值给 param。 // //关闭文件流,并返回反序列化后的对象。 // if (File.Exists(strFile)) // { // Stream stream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.Read); // param = xs.Deserialize(stream) as T; // stream.Close(); // return param; // } // else // { // //如果文件不存在,先创建一个 FileStream 对象,以 FileMode.Create 模式打开文件,将 param 对象序列化为 XML 数据并写入文件。 // //再次打开文件,读取其中的 XML 数据进行反序列化,并返回反序列化后的对象。 // Stream stream = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read); // xs.Serialize(stream, param); // stream.Close(); // stream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.Read); // param = xs.Deserialize(stream) as T; // stream.Close(); // return param; // } // } // } // catch (Exception ex) // { // bReadOK = false; // MessageBox.Show(ex.Message); // } // return null; // } //} /// /// 通过文件名寻找同目录下的其他同类型文件 /// /// 文件的绝对路径名 public static List GetFile(string file) { List listFile = new List(); if (!string.IsNullOrEmpty(file) && File.Exists(file)) { int index = file.LastIndexOf("\\"); if (-1 == index) return null; string path = file.Substring(0, index);//文件所在文件夹路径 string name = file.Substring(index);//文件名 string postfix = "";//取出后缀名 if (name.Contains(".")) { postfix = name.Substring(name.LastIndexOf('.'));//例: .txt } else { return null; } string[] files = null; try { files = Directory.GetFiles(path); } catch (Exception ex) { MessageBox.Show(ex.Message); return null; } foreach (var item in files) { int nIndex = item.IndexOf(postfix); if (nIndex != -1) { listFile.Add(item); } } } return listFile; } #region 对注册表进行读写 //public static void CreatRegistryPath(string strPathName) //{ // try // { // RegistryKey key = Registry.LocalMachine; // //RegistryKey software = key.CreateSubKey("software\\test"); // RegistryKey software = key.CreateSubKey("software\\" + strPathName); // key.Close(); // } // catch (Exception ex) // { // MessageBox.Show("对注册表创建路径时出现异常!" + ex.Message); // } //} //public static void DeleteRegistryPath(string strPathName) //{ // try // { // RegistryKey key = Registry.LocalMachine; // //key.DeleteSubKey("software\\test", true); // key.DeleteSubKey("software\\" + strPathName, true); // key.Close(); // } // catch (Exception ex) // { // MessageBox.Show("对注册表删除路径时出现异常!" + ex.Message); // } //} //public static void SetRegistryValue(string strPathName, string strKey, string strValue) //{ // try // { // RegistryKey key = Registry.LocalMachine; // RegistryKey software = key.OpenSubKey("software\\" + strPathName, true); // //software.SetValue("test", "博客园"); // software.SetValue(strKey, strValue); // key.Close(); // } // catch (Exception ex) // { // MessageBox.Show("对注册表设置键值时出现异常!" + ex.Message); // } //} //public static string GetRegistryValue(string strPathName, string strKey) //{ // try // { // RegistryKey Key = Registry.LocalMachine; // RegistryKey myreg = Key.OpenSubKey("software\\" + strPathName, true); // //info = myreg.GetValue("test").ToString(); // string strValue = myreg.GetValue(strKey).ToString(); // myreg.Close(); // return strValue; // } // catch (Exception ex) // { // MessageBox.Show("对注册表获取值时出现异常!" + ex.Message); // return ""; // } //} //public static void DeleteRegistryKey(string strPathName, string strKey) //{ // try // { // RegistryKey delKey = Registry.LocalMachine.OpenSubKey("Software\\" + strPathName, true); // //delKey.DeleteValue("test"); // delKey.DeleteValue(strKey); // delKey.Close(); // } // catch (Exception ex) // { // MessageBox.Show("对注册表删除键值时出现异常!" + ex.Message); // } //} #endregion #region 深度拷贝 public static T DeepCopy(T obj) { if (obj == null) return default; //var json = JsonConvert.SerializeObject(obj); //return JsonConvert.DeserializeObject(json); var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; string json = JsonConvert.SerializeObject(obj, settings); return JsonConvert.DeserializeObject(json, settings); } [Obsolete("弃用,使用上面的DeepCopy方法")] public static T DeepCopy_1(T obj) { if (obj == null) return default; Type actualType = obj.GetType(); // 处理值类型和字符串 // 处理值类型和字符串 if (actualType.IsValueType || actualType == typeof(string)) return obj; // 处理数组 if (actualType.IsArray) { var elementType = typeof(T).GetElementType(); var sourceArray = (Array)(object)obj; var copiedArray = Array.CreateInstance(elementType, sourceArray.Length); for (int i = 0; i < sourceArray.Length; i++) { copiedArray.SetValue(DeepCopy((dynamic)sourceArray.GetValue(i)), i); } return (T)(object)copiedArray; } // 处理集合(如 List, ObservableCollection) // 处理集合(优先直接创建目标类型,避免冗余转换) if (typeof(IEnumerable).IsAssignableFrom(actualType) && actualType != typeof(string)) { return DeepCopyCollection(obj); } // 处理普通对象(核心修改) // 关键修改2:按“实际类型”创建实例(而非 T 的声明类型) object copy = Activator.CreateInstance(actualType); // 关键修改3:拷贝所有字段(包括私有字段+派生类特有字段) FieldInfo[] fields = actualType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (var field in fields) { if (field.IsStatic) continue; // 跳过静态字段 var value = field.GetValue(obj); // 递归深拷贝字段值(保持原逻辑) var copiedValue = DeepCopy((dynamic)value); field.SetValue(copy, copiedValue); } // 强制转换为 T(因为实际类型是 T 的派生类,转换安全) return (T)copy; } /// /// 专门处理 ObservableCollection 类型属性(支持只读属性) /// private static void DeepCopyObservableCollectionProperty(PropertyInfo property, object sourceObj, object targetObj) { // 获取源集合和元素类型 var sourceCollection = property.GetValue(sourceObj) as IEnumerable; var elementType = property.PropertyType.GetGenericArguments()[0]; // 创建新的 ObservableCollection 实例(匹配原属性类型) var targetCollection = Activator.CreateInstance(property.PropertyType) as IList; if (targetCollection == null) throw new InvalidOperationException($"无法创建 {property.PropertyType.Name} 实例"); // 深拷贝集合元素并添加到新集合 foreach (var item in sourceCollection) { var copiedItem = DeepCopy((dynamic)item); targetCollection.Add(copiedItem); } // 给目标对象赋值:可写属性直接 SetValue,只读属性通过底层字段赋值 if (property.CanWrite) { property.SetValue(targetObj, targetCollection); } else { // 匹配只读属性的底层字段(常见命名规范:_propertyName 或 m_propertyName) var fieldName = $"_{char.ToLower(property.Name[0])}{property.Name.Substring(1)}"; var field = targetObj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); // 若未匹配到,尝试 mPropertyName 规范 if (field == null) { fieldName = $"m{property.Name}"; field = targetObj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); } if (field != null && field.FieldType == property.PropertyType) { field.SetValue(targetObj, targetCollection); } else { throw new InvalidOperationException($"无法给只读属性 {property.DeclaringType.Name}.{property.Name} 赋值,请检查字段命名(预期:{fieldName})"); } } } /// /// 优化集合深拷贝:直接创建目标类型集合,避免 List 中转 /// private static T DeepCopyCollection(T sourceCollection) { var sourceType = typeof(T); var elementType = sourceType.IsGenericType ? sourceType.GetGenericArguments()[0] : typeof(object); // 直接创建目标类型的集合实例(如 ObservableCollection) var targetCollection = Activator.CreateInstance(sourceType) as IList; if (targetCollection == null) throw new InvalidOperationException($"无法创建集合类型 {sourceType.Name} 实例"); // 深拷贝每个元素并添加到新集合 foreach (var item in (IEnumerable)sourceCollection) { var copiedItem = DeepCopy((dynamic)item); targetCollection.Add(copiedItem); } return (T)targetCollection; } public static ObservableCollection DeepCopyObservableCollection(ObservableCollection source) { // 序列化为 JSON 字符串 var json = JsonConvert.SerializeObject(source); // 从 JSON 字符串反序列化为新对象 return JsonConvert.DeserializeObject>(json); } #endregion } }