一个DeepCopyParameterHelper类,帮助深拷贝各种类型的对象(如果有BUG,欢迎留言讨论)
public class DeepCopyParameterHelper
{
private DeepCopyParameterHelper() { }
/// <summary>
/// Deep copy, implemented by serialization and deserialization
/// </summary>
/// <typeparam name="T">The class type of the deep copy</typeparam>
/// <param name="obj">Deep copy class objects</param>
/// <returns></returns>
public static T DeepCopyByBin<T>(T obj)
{
if (obj == null)
return default(T);
//If it is a string or value type, it is returned directly
if (obj is string || obj.GetType().IsValueType) return obj;
object retval;
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
//Serialize to stream
bf.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
//Deserialize to an object
retval = bf.Deserialize(ms);
ms.Close();
}
return (T)retval;
}
/// <summary>
/// Deep copy, implemented by reflection
/// </summary>
/// <typeparam name="T">The class type of the deep copy</typeparam>
/// <param name="obj">Deep copy class objects</param>
/// <returns></returns>
public static T DeepCopyByReflect<T>(T obj)
{
try
{
if (obj == null)
return default(T);
//If it is a string or value type or is null, it is returned directly
if (obj is string || obj is int || obj.GetType().IsValueType) return obj;
var type = obj.GetType();
if (type.Name.ToLower().Contains("int") || type.Name == "Entry[]")
return obj;
object retval = Activator.CreateInstance(type);
FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
foreach (FieldInfo field in fields)
{
try
{
if (field.FieldType.Name.Equals("List`1"))
{
var t1 = field.FieldType.GenericTypeArguments[0];
MethodInfo mi = typeof(DeepCopyParameterHelper).GetMethod("DeepCopyList")?.MakeGenericMethod(new Type[] { t1 });
if (mi != null)
{
var result = mi.Invoke(typeof(DeepCopyParameterHelper), new[] { field.GetValue(obj) });
field.SetValue(retval, result);
}
}
else if (field.FieldType.Name.Equals("Dictionary`2"))
{
var t1 = field.FieldType.BaseType;
MethodInfo mi = typeof(DeepCopyParameterHelper).GetMethod("DeepCopyDictionary")?.MakeGenericMethod(new Type[] { t1 });
if (mi != null)
{
var result = mi.Invoke(typeof(DeepCopyParameterHelper), new[] { field.GetValue(obj) });
field.SetValue(retval, result);
}
}
else
{
field.SetValue(retval, DeepCopyByReflect(field.GetValue(obj)));
}
}
catch (Exception)
{
// ignored
}
}
return (T)retval;
}
catch (Exception ex)
{
return default;
}
}
/// <summary>
/// Clones the specified list.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list">The list.</param>
/// <returns>List{``0}.</returns>
public static List<T> DeepCopyList<T>(object list)
{
List<T> result = new List<T>();
if (list != null)
{
foreach (var item in ((List<T>) list))
{
var type = item.GetType();
if (type.Name.Equals("Dictionary`2") || type.Name.Equals("KeyCollection"))
{
result.Add((T)DeepCopyDictionary(item));
}
else
{
result.Add(DeepCopyByReflect(item));
}
}
}
return result;
}
public static object DeepCopyDictionary(object obj)
{
IDictionary srcDictionary = obj as IDictionary;
if (srcDictionary != null && srcDictionary.Count > 0)
{
// Create new map instance
IDictionary dstDictionary = Activator.CreateInstance(srcDictionary.GetType()) as IDictionary;
// deep copy each object in map
foreach (object o in srcDictionary.Keys)
{
if (dstDictionary != null) dstDictionary[o] = srcDictionary[o];
}
return dstDictionary;
}
return srcDictionary;
}
}
雷区:
有些类把构造函数初始化加参数了,就会在以下这个地方抛异常,就会返回null,望周知
object retval = Activator.CreateInstance(type);