C00225155-02/C00225155/MegaRobo.C00225155/Common/File_Operator.cs

439 lines
17 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<T>(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;
}
}
/// <summary>
/// XML文件读写
/// 保存配置参数 bReadOK==false为发生异常
/// </summary>
/// <typeparam name="T">类类型</typeparam>
/// <param name="strFile">完整文件路径名</param>
/// <param name="bSave">true:保存false:读取</param>
/// <param name="param">要进行序列化或反序列化的对象实例</param>
/// <param name="bReadOK">是否读写成功,有异常</param>
/// <returns>读取的数据</returns>
//public static T Xml_Serialize<T>(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;
// }
//}
/// <summary>
/// 通过文件名寻找同目录下的其他同类型文件
/// </summary>
/// <param name="file">文件的绝对路径名</param>
public static List<string> GetFile(string file)
{
List<string> listFile = new List<string>();
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>(T obj)
{
if (obj == null) return default;
//var json = JsonConvert.SerializeObject(obj);
//return JsonConvert.DeserializeObject<T>(json);
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
string json = JsonConvert.SerializeObject(obj, settings);
return JsonConvert.DeserializeObject<T>(json, settings);
}
[Obsolete("弃用使用上面的DeepCopy方法")]
public static T DeepCopy_1<T>(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<T>(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;
}
/// <summary>
/// 专门处理 ObservableCollection 类型属性(支持只读属性)
/// </summary>
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}");
}
}
}
/// <summary>
/// 优化集合深拷贝:直接创建目标类型集合,避免 List 中转
/// </summary>
private static T DeepCopyCollection<T>(T sourceCollection)
{
var sourceType = typeof(T);
var elementType = sourceType.IsGenericType ? sourceType.GetGenericArguments()[0] : typeof(object);
// 直接创建目标类型的集合实例(如 ObservableCollection<SampleBottleModel>
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<T> DeepCopyObservableCollection<T>(ObservableCollection<T> source)
{
// 序列化为 JSON 字符串
var json = JsonConvert.SerializeObject(source);
// 从 JSON 字符串反序列化为新对象
return JsonConvert.DeserializeObject<ObservableCollection<T>>(json);
}
#endregion
}
}