You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
4.9 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using Newtonsoft.Json;
namespace POSV.Utils
{
public static class ObjectUtils
{
//要复制的实例必须可序列化,包括实例引用的其它实例都必须在类定义时加[Serializable]特性。
public static T Copy<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable." , "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source , null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream , source);
stream.Seek(0 , SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
public static void CopyTo(this object S , object T)
{
foreach (var pS in S.GetType().GetProperties())
{
foreach (var pT in T.GetType().GetProperties())
{
if (pT.Name != pS.Name) continue;
(pT.GetSetMethod()).Invoke(T , new object[]{ pS.GetGetMethod().Invoke( S, null ) });
}
};
}
private static Dictionary<string , object> _Dic = new Dictionary<string , object>();
public static TOut TransExp<TIn, TOut>(TIn tIn)
{
string key = string.Format("trans_exp_{0}_{1}" , typeof(TIn).FullName , typeof(TOut).FullName);
if (!_Dic.ContainsKey(key))
{
ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn) , "p");
List<MemberBinding> memberBindingList = new List<MemberBinding>();
foreach (var item in typeof(TOut).GetProperties())
{
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 });
Func<TIn , TOut> func = lambda.Compile();
_Dic[key] = func;
}
return ((Func<TIn , TOut>)_Dic[key])(tIn);
}
public static T CloneJson<T>(this T source)
{
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source , null))
{
return default(T);
}
// initialize inner objects individually
// for example in default constructor some list property initialized with some values,
// but in 'source' these items are cleaned -
// without ObjectCreationHandling.Replace default constructor values will be added to result
var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace };
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source) , deserializeSettings);
}
}
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);
}
}
}