V1.2
This commit is contained in:
277
CapMachine.Core/DeepCopyHelper.cs
Normal file
277
CapMachine.Core/DeepCopyHelper.cs
Normal file
@@ -0,0 +1,277 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace CapMachine.Core
|
||||
{
|
||||
public class DeepCopyHelper
|
||||
{
|
||||
// 用一个字典来存放每个对象的反射次数来避免反射代码的循环递归
|
||||
static readonly Dictionary<Type, int> TypereflectionCountDic = new Dictionary<Type, int>();
|
||||
//static object _deepCopyDemoClasstypeRef = null;
|
||||
// 利用反射实现深拷贝
|
||||
public static T DeepCopyWithReflection<T>(T obj)
|
||||
{
|
||||
Type type = obj.GetType();
|
||||
// 如果是字符串或值类型则直接返回
|
||||
if (obj is string || type.IsValueType) return obj;
|
||||
if (type.IsArray)
|
||||
{
|
||||
if (type.FullName != null)
|
||||
{
|
||||
Type elementType = Type.GetType(type.FullName.Replace("[]", string.Empty));
|
||||
var array = obj as Array;
|
||||
if (array != null)
|
||||
{
|
||||
Array copied = Array.CreateInstance(elementType ?? throw new InvalidOperationException(), array.Length);
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
copied.SetValue(DeepCopyWithReflection(array.GetValue(i)), i);
|
||||
}
|
||||
return (T)Convert.ChangeType(copied, obj.GetType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object retval = Activator.CreateInstance(obj.GetType());
|
||||
|
||||
PropertyInfo[] properties = obj.GetType().GetProperties(
|
||||
BindingFlags.Public | BindingFlags.NonPublic
|
||||
| BindingFlags.Instance | BindingFlags.Static);
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var propertyValue = property.GetValue(obj, null);
|
||||
if (propertyValue == null)
|
||||
continue;
|
||||
property.SetValue(retval, DeepCopyWithReflection(propertyValue), null);
|
||||
}
|
||||
return (T)retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static T DeepCopyWithReflection_Second<T>(T obj)
|
||||
{
|
||||
Type type = obj.GetType();
|
||||
|
||||
// 如果是字符串或值类型则直接返回
|
||||
if (obj is string || type.IsValueType) return obj;
|
||||
if (type.IsArray)
|
||||
{
|
||||
if (type.FullName != null)
|
||||
{
|
||||
Type elementType = Type.GetType(type.FullName.Replace("[]", string.Empty));
|
||||
var array = obj as Array;
|
||||
if (array != null)
|
||||
{
|
||||
Array copied = Array.CreateInstance(elementType ?? throw new InvalidOperationException(), array.Length);
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
copied.SetValue(DeepCopyWithReflection_Second(array.GetValue(i)), i);
|
||||
}
|
||||
return (T)Convert.ChangeType(copied, obj.GetType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 对于类类型开始记录对象反射的次数
|
||||
int reflectionCount = Add(TypereflectionCountDic, obj.GetType());
|
||||
if (reflectionCount > 1)
|
||||
return obj;
|
||||
|
||||
object retval = Activator.CreateInstance(obj.GetType());
|
||||
|
||||
PropertyInfo[] properties = obj.GetType().GetProperties(
|
||||
BindingFlags.Public | BindingFlags.NonPublic
|
||||
| BindingFlags.Instance | BindingFlags.Static);
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var propertyValue = property.GetValue(obj, null);
|
||||
if (propertyValue == null)
|
||||
continue;
|
||||
property.SetValue(retval, DeepCopyWithReflection_Second(propertyValue), null);
|
||||
}
|
||||
return (T)retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//public static T DeepCopyWithReflection_Third<T>(T obj)
|
||||
//{
|
||||
// Type type = obj.GetType();
|
||||
// // 如果是字符串或值类型则直接返回
|
||||
// if (obj is string || type.IsValueType) return obj;
|
||||
// if (type.IsArray)
|
||||
// {
|
||||
// Type elementType = Type.GetType(type.FullName.Replace("[]", string.Empty));
|
||||
// var array = obj as Array;
|
||||
// Array copied = Array.CreateInstance(elementType, array.Length);
|
||||
// for (int i = 0; i < array.Length; i++)
|
||||
// {
|
||||
// copied.SetValue(DeepCopyWithReflection_Second(array.GetValue(i)), i);
|
||||
// }
|
||||
// return (T) Convert.ChangeType(copied, obj.GetType());
|
||||
// }
|
||||
// int reflectionCount = Add(typereflectionCountDic, obj.GetType());
|
||||
// if (reflectionCount > 1 && obj.GetType() == typeof(DeepCopyDemoClass))
|
||||
// return (T) DeepCopyDemoClasstypeRef; // 返回deepCopyClassB对象
|
||||
// object retval = Activator.CreateInstance(obj.GetType());
|
||||
// if (retval.GetType() == typeof(DeepCopyDemoClass))
|
||||
// DeepCopyDemoClasstypeRef = retval; // 保存一开始创建的DeepCopyDemoClass对象
|
||||
// PropertyInfo[] properties = obj.GetType().GetProperties(
|
||||
// BindingFlags.Public | BindingFlags.NonPublic
|
||||
// | BindingFlags.Instance | BindingFlags.Static);
|
||||
// foreach (var property in properties)
|
||||
// {
|
||||
// var propertyValue = property.GetValue(obj, null);
|
||||
// if (propertyValue == null)
|
||||
// continue;
|
||||
// property.SetValue(retval, DeepCopyWithReflection_Third(propertyValue), null);
|
||||
// }
|
||||
// return (T) retval;
|
||||
//}
|
||||
|
||||
//private static T SetArrayObject<T>(T arrayObj)
|
||||
//{
|
||||
// Type elementType = Type.GetType(arrayObj.GetType().FullName.Replace("[]", string.Empty));
|
||||
// var array = arrayObj as Array;
|
||||
// Array copied = Array.CreateInstance(elementType, array.Length);
|
||||
// for (int i = 0; i < array.Length; i++)
|
||||
// {
|
||||
// copied.SetValue(DeepCopyWithReflection_Third(array.GetValue(i)), i);
|
||||
// }
|
||||
// return (T) Convert.ChangeType(copied, arrayObj.GetType());
|
||||
//}
|
||||
|
||||
private static int Add(Dictionary<Type, int> dict, Type key)
|
||||
{
|
||||
if (key == typeof(string) || key.IsValueType) return 0;
|
||||
if (!dict.ContainsKey(key))
|
||||
{
|
||||
dict.Add(key, 1);
|
||||
return dict[key];
|
||||
}
|
||||
dict[key] += 1;
|
||||
return dict[key];
|
||||
}
|
||||
|
||||
// 利用XML序列化和反序列化实现
|
||||
public static T DeepCopyWithXmlSerializer<T>(T obj)
|
||||
{
|
||||
object retval;
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
XmlSerializer xml = new XmlSerializer(typeof(T));
|
||||
xml.Serialize(ms, obj);
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
retval = xml.Deserialize(ms);
|
||||
ms.Close();
|
||||
}
|
||||
return (T)retval;
|
||||
}
|
||||
|
||||
// 利用二进制序列化和反序列实现(亲测有用)
|
||||
public static T DeepCopyWithBinarySerialize<T>(T obj)
|
||||
{
|
||||
object retval;
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
// 序列化成流
|
||||
bf.Serialize(ms, obj);
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
// 反序列化成对象
|
||||
retval = bf.Deserialize(ms);
|
||||
ms.Close();
|
||||
}
|
||||
return (T)retval;
|
||||
}
|
||||
|
||||
// 利用DataContractSerializer序列化和反序列化实现
|
||||
//public static T DeepCopy<T>(T obj)
|
||||
//{
|
||||
// object retval;
|
||||
// using (MemoryStream ms = new MemoryStream())
|
||||
// {
|
||||
// DataContractSerializer ser = new DataContractSerializer(typeof(T));
|
||||
// ser.WriteObject(ms, obj);
|
||||
// ms.Seek(0, SeekOrigin.Begin);
|
||||
// retval = ser.ReadObject(ms);
|
||||
// ms.Close();
|
||||
// }
|
||||
// return (T) retval;
|
||||
//}
|
||||
// 表达式树实现
|
||||
// ....
|
||||
public static class TransExpV2<TIn, TOut>
|
||||
{
|
||||
private static readonly Func<TIn, TOut> cache = GetFunc();
|
||||
private static Func<TIn, TOut> GetFunc()
|
||||
{
|
||||
ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
|
||||
List<MemberBinding> memberBindingList = new List<MemberBinding>();
|
||||
|
||||
foreach (var item in typeof(TOut).GetProperties())
|
||||
{
|
||||
if (!item.CanWrite)
|
||||
continue;
|
||||
|
||||
MemberExpression property =
|
||||
Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
|
||||
|
||||
MemberBinding memberBinding = Expression.Bind(item, property);
|
||||
memberBindingList.Add(memberBinding);
|
||||
}
|
||||
MemberInitExpression memberInitExpression =
|
||||
Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
|
||||
|
||||
Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression,
|
||||
new ParameterExpression[] { parameterExpression });
|
||||
return lambda.Compile();
|
||||
}
|
||||
|
||||
public static TOut Trans(TIn tIn)
|
||||
{
|
||||
return cache(tIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//public static class TransExpV2<TIn, TOut>
|
||||
//{
|
||||
|
||||
// private static readonly Func<TIn, TOut> cache = GetFunc();
|
||||
// private static Func<TIn, TOut> GetFunc()
|
||||
// {
|
||||
// ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
|
||||
// List<MemberBinding> memberBindingList = new List<MemberBinding>();
|
||||
|
||||
// foreach (var item in typeof(TOut).GetProperties())
|
||||
// {
|
||||
// if (!item.CanWrite) continue;
|
||||
// MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
|
||||
// MemberBinding memberBinding = Expression.Bind(item, property);
|
||||
// memberBindingList.Add(memberBinding);
|
||||
// }
|
||||
|
||||
// MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
|
||||
// Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[] { parameterExpression });
|
||||
|
||||
// return lambda.Compile();
|
||||
// }
|
||||
|
||||
// public static TOut Trans(TIn tIn)
|
||||
// {
|
||||
// return cache(tIn);
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user