C# 带有表达式的深度克隆。新建和表达式树
我有两个生成的接口C# 带有表达式的深度克隆。新建和表达式树,c#,expression-trees,deep-copy,C#,Expression Trees,Deep Copy,我有两个生成的接口IPerson和iadress 但是,我已经定义了从这些基本接口继承的属性接口 接口 public接口IPerson\u Name:IPerson{String Name{get;set;} 公共接口IPerson_地址:IPerson { ICollection地址{get;set;} 新地址(); } 公共界面IAddress\u第1行:IAddress { 字符串行1{get;set;} } 然后我有两个基本接口的实现 实施 公共类人员:IPerson { 公共字符串名
IPerson
和iadress
但是,我已经定义了从这些基本接口继承的属性接口
接口
public接口IPerson\u Name:IPerson{String Name{get;set;}
公共接口IPerson_地址:IPerson
{
ICollection地址{get;set;}
新地址();
}
公共界面IAddress\u第1行:IAddress
{
字符串行1{get;set;}
}
然后我有两个基本接口的实现
实施
公共类人员:IPerson
{
公共字符串名称{get;set;}
公共ICollection
编辑
我已将基本参数复制到新版本。到目前为止,它对基本属性有效。我已更新了上面的代码编辑:显然linq to entities无法理解这些表达式中的方法调用。因此,这没有帮助
实现以下接口的接口将能够复制其公共接口的属性
public interface IEntity
{
}
public interface IEntityObject : IEntity
{
}
public interface IEntityCollection : IEntity
{
}
public interface IEntityProperty : IEntity
{
}
然后,对于实体的每个属性,您需要创建一个接口
public interface IThing:IEntity{}
public interface IThing_Property: IThing, IEntityProperty
{
int SimpleProperty{get;set;}
}
public interface IThing_ComplexProperty: IThing, IEntityObject{}
public interface IThing_ComplexProperty<T> : IEntity_ComplexProperty where T:class, IEntity,new()
{
T SomeProperty{get;set;}
}
public interface IThing_CollectionProperty: IThing, IEntityCollection{}
public interface IThing_CollectionProperty<T> :IEntity_CollectionProperty where T:class, IEntity,new()
{
IEnumerable<T> SomeCollectionProperty{get;set;}
}
公共接口信息:IEntity{}
公共接口IThing_属性:IThing,IEntityProperty
{
int SimpleProperty{get;set;}
}
公共接口IThing_ComplexProperty:IThing,IEntityObject{}
公共接口IThing\u ComplexProperty:IEntity\u ComplexProperty其中T:class,IEntity,new()
{
T SomeProperty{get;set;}
}
公共接口IThing_CollectionProperty:IThing,IEntityCollection{}
公共接口IThing_CollectionProperty:IEntity_CollectionProperty,其中T:class,IEntity,new()
{
IEnumerable SomeCollectionProperty{get;set;}
}
现在如果你这样做了
IQueryable<SomeThingImpl> x;
IQueryable<SomeOtherThingImpl> y = x.CopyTo<SomeThingImpl,SomeOtherThingImpl>()
IQueryable x;
IQueryable y=x.CopyTo()
在它列举之前,我还不会被召唤
此外,如果泛型类型共享任何IEntity接口,它们也将被复制
暂时
下面是这些类的外观
public static class CopyToExt
{
private static readonly ConcurrentDictionary<Type, LambdaExpression> expressions;
private static readonly ConcurrentDictionary<Type, Object> funcs;
private static readonly ConcurrentDictionary<Type, LambdaExpression> mergeStackExpr;
private static ConcurrentDictionary<Type, Object> mergeStackFunc;
public static MethodInfo AsQueryableMethod;
public static MethodInfo SelectMethod;
public static MethodInfo ToListMethod;
public static MethodInfo CopyToMethod;
public static MethodInfo AddMergeMethod;
public static MethodInfo CreateMergeMethod;
public static MethodInfo TryCopyMethod;
static CopyToExt()
{
mergeStackExpr = new ConcurrentDictionary<Type, LambdaExpression>(new Dictionary<Type, LambdaExpression>());
foreach (MethodInfo m in typeof(Queryable).GetMethods().Where(m => m.Name == "Select"))
foreach (ParameterInfo p in m.GetParameters().Where(p => p.Name.Equals("selector")))
if (p.ParameterType.GetGenericArguments().Any(x => x.GetGenericArguments().Count() == 2))
SelectMethod = (MethodInfo)p.Member;
foreach (MethodInfo m in typeof(Enumerable).GetMethods().Where(m => m.Name == "ToList"))
foreach (ParameterInfo p in m.GetParameters().Where(p => p.Name.Equals("source")))
if (p.ParameterType.GetGenericArguments().Count() == 1)
ToListMethod = (MethodInfo)p.Member;
foreach (MethodInfo m in typeof(Queryable).GetMethods().Where(m => m.Name == "AsQueryable"))
foreach (ParameterInfo p in m.GetParameters().Where(p => p.Name.Equals("source")))
if (p.ParameterType.GetGenericArguments().Count() == 1)
AsQueryableMethod = (MethodInfo)p.Member;
CreateMergeMethod = typeof(CopyToExt).GetMethods().First(m => m.Name == "CreateMergeStack");
AddMergeMethod = typeof(MergeStack).GetMethods().First(m => m.Name == "AddReturnOrCreateAddReturn");
TryCopyMethod = typeof(MergeStack).GetMethods().First(m => m.Name == "TryCopy");
}
public static IQueryable<TDest> CopyTo<TSrc, TDest>(this IQueryable<TSrc> queryable)
where TSrc : class, IEntity
where TDest : class, IEntity
{
var copyExpr = CreateTryCopy<TSrc, TDest>();
var ms = CreateMergeStack<TSrc>();
return queryable.Select(ms).Select(copyExpr);
}
public static IEnumerable<TDest> CopyTo<TSrc, TDest>(this IEnumerable<TSrc> queryable)
where TSrc : class, IEntity
where TDest : class, IEntity
{
return queryable.AsQueryable().CopyTo<TSrc, TDest>().AsEnumerable();
}
public static Expression<Func<TSrc, Stackholder<TSrc>>> CreateMergeStack<TSrc>()
{
return mergeStackExpr.GetOrAdd(typeof(TSrc), (type) =>
{
var shtype = typeof(Stackholder<TSrc>);
var parm = Expression.Parameter(typeof(TSrc));
var destNewExpr = Expression.New(shtype);
var methodcall = Expression.Call(null,
CopyToExt.AddMergeMethod);
var memInit = Expression.MemberInit(destNewExpr,
Expression.Bind(shtype.GetField("Src"), parm),
Expression.Bind(shtype.GetField("Ms"), methodcall));
return Expression.Lambda<Func<TSrc, Stackholder<TSrc>>>(memInit, parm);
}) as Expression<Func<TSrc, Stackholder<TSrc>>>;
}
public static Expression<Func<Stackholder<TSrc>, TDest>> CreateTryCopy<TSrc, TDest>()
{
var shtype = typeof(Stackholder<TSrc>);
var parentParam = Expression.Parameter(shtype);
var SrcExpr = Expression.PropertyOrField(parentParam, "Src");
var MSExpr = Expression.PropertyOrField(parentParam, "Ms");
var tcMethod = Expression.Call(MSExpr,
TryCopyMethod.MakeGenericMethod(new Type[] { typeof(TSrc), typeof(TDest) }),
SrcExpr);
return Expression.Lambda<Func<Stackholder<TSrc>, TDest>>(tcMethod, parentParam);
}
internal static bool Impliments(this Type type, Type inheritedType)
{
return (type.IsSubclassOf(inheritedType) || type.GetInterface(inheritedType.FullName) != null);
}
internal static bool Impliments<T>(this Type type, Type inheritedType = null)
{
return type.Impliments(typeof(T));
}
private static ConcurrentDictionary<Type, Object> AssignDict =
new ConcurrentDictionary<Type, Object>(new Dictionary<Type, Object>());
internal static Func<TSrc, TDest, MergeStack, TDest> Assign<TSrc, TDest>()
{
return (Func<TSrc, TDest, MergeStack, TDest>) AssignDict.GetOrAdd(typeof (Func<TSrc, TDest>), (indexType) =>
{
var tSrc = typeof (TSrc);
var tDest = typeof (TDest);
var srcEntityInterfaces = tSrc.GetInterfaces().Where(x => x.Impliments<IEntity>());
var destEntityInterfaces = tDest.GetInterfaces().Where(x => x.Impliments<IEntity>());
var srcParam = Expression.Parameter(tSrc);
var destParam = Expression.Parameter(tDest);
var MSExpr = Expression.Parameter(typeof (MergeStack));
var common = destEntityInterfaces.Intersect(srcEntityInterfaces);
var memberbindings = common.Where(x => x.Impliments<IEntityProperty>())
.Select(type => type.GetProperties().First())
.Select(
prop =>
Expression.Assign(Expression.Property(destParam, prop.Name),
Expression.Property(srcParam, prop.Name)))
.Cast<Expression>().ToList();
foreach (var type in common.Where(x => x.Impliments<IEntityObject>()))
{
var destSubType = destEntityInterfaces.First(x => x.Impliments(type))
.GetGenericArguments()
.First();
var srcSubType = srcEntityInterfaces.First(x => x.Impliments(type))
.GetGenericArguments()
.First();
var dProp = destEntityInterfaces.First(x => x.Impliments(type)).GetProperties().First();
var sProp = srcEntityInterfaces.First(x => x.Impliments(type)).GetProperties().First();
var tcParam = Expression.Parameter(srcSubType);
var tcMethod = Expression.Call(MSExpr,
TryCopyMethod.MakeGenericMethod(new Type[] {srcSubType, destSubType}),
tcParam);
LambdaExpression mergeLambda = Expression.Lambda(tcMethod, tcParam);
MemberExpression memberExpression = Expression.Property(srcParam, sProp.Name);
InvocationExpression invocationExpression = Expression.Invoke(mergeLambda,
Expression.Property(srcParam, sProp.Name));
var check = Expression.Condition(
Expression.MakeBinary(ExpressionType.NotEqual, memberExpression,
Expression.Constant(null, sProp.PropertyType)), invocationExpression,
Expression.Constant(null, invocationExpression.Type));
BinaryExpression binaryExpression = Expression.Assign(Expression.Property(destParam, dProp.Name),
check);
memberbindings.Add(binaryExpression);
}
foreach (var type in common.Where(x => x.Impliments<IEntityCollection>()))
{
var destSubType = destEntityInterfaces.First(x => x.Impliments(type))
.GetGenericArguments()
.First();
var srcSubType = srcEntityInterfaces.First(x => x.Impliments(type))
.GetGenericArguments()
.First();
var dProp = destEntityInterfaces.First(x => x.Impliments(type)).GetProperties().First();
var sProp = srcEntityInterfaces.First(x => x.Impliments(type)).GetProperties().First();
var tcParam = Expression.Parameter(srcSubType);
var tcMethod = Expression.Call(MSExpr,
TryCopyMethod.MakeGenericMethod(new Type[] {srcSubType, destSubType}),
tcParam);
LambdaExpression mergeLambda = Expression.Lambda(tcMethod, tcParam);
var memberExpression = Expression.Property(srcParam, sProp.Name);
var selectExpr = Expression.Call(null,
AsQueryableMethod.MakeGenericMethod(new Type[] {srcSubType}),
new Expression[] {memberExpression});
selectExpr = Expression.Call(null,
CopyToExt.SelectMethod.MakeGenericMethod(new Type[] {srcSubType, destSubType}),
new Expression[] {selectExpr, mergeLambda});
selectExpr = Expression.Call(null,
CopyToExt.ToListMethod.MakeGenericMethod(new Type[] {destSubType}),
new Expression[] {selectExpr});
var check = Expression.Condition(
Expression.MakeBinary(ExpressionType.NotEqual, memberExpression,
Expression.Constant(null, sProp.PropertyType)), selectExpr,
Expression.Constant(null, selectExpr.Type));
memberbindings.Add(Expression.Assign(Expression.Property(destParam, dProp.Name), check));
}
memberbindings.Add(destParam);
return
Expression.Lambda<Func<TSrc, TDest, MergeStack, TDest>>(Expression.Block(memberbindings),
new ParameterExpression[] {srcParam, destParam, MSExpr}).Compile();
});
}
}
public class Stackholder<TSrc>
{
public MergeStack Ms;
public TSrc Src;
}
public class MergeStack
{
private static ConcurrentDictionary<Thread, MergeStack> StackDict = new ConcurrentDictionary<Thread, MergeStack>(new Dictionary<Thread, MergeStack>());
private readonly Dictionary<Type, Dictionary<Object, Object>> _mergeObjDict = new Dictionary<Type, Dictionary<object, object>>();
public static MergeStack AddReturnOrCreateAddReturn()
{
return StackDict.GetOrAdd(Thread.CurrentThread, (x) => new MergeStack() { });
}
public TDest TryCopy<TSrc, TDest>(TSrc Src)
where TSrc : class, IEntity
where TDest : class, IEntity, new()
{
if (Src == null) return null;
var objToIndex = new TDest();
Dictionary<object, object> objToObj;
if (!_mergeObjDict.ContainsKey(objToIndex.GetType()))
{
objToObj = new Dictionary<object, object>();
_mergeObjDict.Add(objToIndex.GetType(), objToObj);
}
else
{
objToObj = _mergeObjDict[objToIndex.GetType()];
}
if (!objToObj.ContainsKey(Src))
{
objToObj.Add(Src, objToIndex);
return CopyToExt.Assign<TSrc, TDest>()(Src, objToIndex, this);
}
return objToObj[Src] as TDest;
}
}
公共静态类CopyToExt
{
私有静态只读ConcurrentDictionary表达式;
私有静态只读ConcurrentDictionary函数;
私有静态只读ConcurrentDictionary mergeStackExpr;
私有静态并发字典mergeStackFunc;
公共静态方法信息AsQueryableMethod;
公共静态方法信息选择方法;
公共静态方法信息托利斯特方法;
公共静态方法信息复制方法;
公共静态MethodInfo AddMergeMethod;
公共静态MethodInfo CreateMergeMethod;
公共静态方法信息检索方法;
静态CopyToExt()
{
mergeStackExpr=新的ConcurrentDictionary(新字典());
foreach(typeof(Queryable).GetMethods()中的MethodInfo m,其中(m=>m.Name==“Select”))
foreach(m.GetParameters()中的ParameterInfo p,其中(p=>p.Name.Equals(“选择器”))
if(p.ParameterType.GetGenericArguments().Any(x=>x.GetGenericArguments().Count()==2))
SelectMethod=(MethodInfo)p.Member;
foreach(typeof中的MethodInfo m(可枚举).GetMethods()。其中(m=>m.Name==“ToList”))
foreach(m.GetParameters()中的ParameterInfo p,其中(p=>p.Name.Equals(“源”))
if(p.ParameterType.GetGenericArguments().Count()==1)
ToListMethod=(MethodInfo)p.Member;
foreach(typeof(Queryable).GetMethods()中的MethodInfo m,其中(m=>m.Name==“AsQueryable”))
foreach(m.GetParameters()中的ParameterInfo p,其中(p=>p.Name.Equals(“源”))
if(p.ParameterType.GetGenericArguments().Count()==1)
AsQueryableMethod=(MethodInfo)p.Member;
CreateMergeMethod=typeof(copytoText).GetMethods().First(m=>m.Name==“CreateMergeStack”);
AddMergeMethod=typeof(MergeStack).GetMethods().First(m=>m.Name==“AddReturnOrCreateAddReturn”);
TryCopyMethod=typeof(MergeStack).GetMethods().First(m=>m.Name==“TryCopy”);
}
公共静态IQueryable CopyTo(此IQueryable可查询)
其中TSrc:类、属性
其中TDest:类、属性
{
var copyExpr=CreateTryCopy();
var ms=CreateMergeStack();
返回可查询的.Select(ms).Select(copyExpr);
}
公共静态IEnumerable CopyTo(此IEnumerable可查询)
其中TSrc:类、属性
其中TDest:类、属性
{
返回queryable.AsQueryable().CopyTo().AsEnumerable();
}
公共静态表达式CreateMergeStack()
{
返回mergeStackExpr.GetOrAdd(typeof(TSrc),(type)=>
{
var shtype=类型(堆垛机);
var parm=Expression.Parameter(typeof(TSrc));
var destNewExpr=Expression.New(shtype);
var methodcall=Expression.Call(null,
CopyToText.AddMergeMethod);
var memInit=Expression.MemberInit(destNewExpr,
表达式.Bind(shtype.GetField(“Src”),parm),
Expression.Bind(shtype.GetField(“Ms”),methodcall));
返回表达式.Lambda(memInit,parm);
})作为表达;
}
公共静态表达式CreateTryCopy()
{
var shtype=类型(堆垛机);
var parentParam=Expression.Parameter(shtype);
var SrcExpr=Expression.PropertyOrField(parentParam,“Src”);
var MSExpr=Expression.PropertyOrField(parentParam,“Ms”);
var tcMethod=Expression.Call(MSExpr,
MakeGenericMethod(新类型[]{typeof(TSrc),typeof(TDest)}),
srcepr);
返回表达式.Lambda(tcMethod,parentParam);
}
内部静态bool实现(此类型,类型inheritedType)
{
return(type.IsSubclassOf(inheritedType)| | type.GetInterface(inheritedType.FullName)!=null);
}
内部静态bool实现(此类型,类型inheritedType=null)
{
返回类型.Impliments(typeof(T));
}
私有静态并发
public interface IThing:IEntity{}
public interface IThing_Property: IThing, IEntityProperty
{
int SimpleProperty{get;set;}
}
public interface IThing_ComplexProperty: IThing, IEntityObject{}
public interface IThing_ComplexProperty<T> : IEntity_ComplexProperty where T:class, IEntity,new()
{
T SomeProperty{get;set;}
}
public interface IThing_CollectionProperty: IThing, IEntityCollection{}
public interface IThing_CollectionProperty<T> :IEntity_CollectionProperty where T:class, IEntity,new()
{
IEnumerable<T> SomeCollectionProperty{get;set;}
}
IQueryable<SomeThingImpl> x;
IQueryable<SomeOtherThingImpl> y = x.CopyTo<SomeThingImpl,SomeOtherThingImpl>()
public static class CopyToExt
{
private static readonly ConcurrentDictionary<Type, LambdaExpression> expressions;
private static readonly ConcurrentDictionary<Type, Object> funcs;
private static readonly ConcurrentDictionary<Type, LambdaExpression> mergeStackExpr;
private static ConcurrentDictionary<Type, Object> mergeStackFunc;
public static MethodInfo AsQueryableMethod;
public static MethodInfo SelectMethod;
public static MethodInfo ToListMethod;
public static MethodInfo CopyToMethod;
public static MethodInfo AddMergeMethod;
public static MethodInfo CreateMergeMethod;
public static MethodInfo TryCopyMethod;
static CopyToExt()
{
mergeStackExpr = new ConcurrentDictionary<Type, LambdaExpression>(new Dictionary<Type, LambdaExpression>());
foreach (MethodInfo m in typeof(Queryable).GetMethods().Where(m => m.Name == "Select"))
foreach (ParameterInfo p in m.GetParameters().Where(p => p.Name.Equals("selector")))
if (p.ParameterType.GetGenericArguments().Any(x => x.GetGenericArguments().Count() == 2))
SelectMethod = (MethodInfo)p.Member;
foreach (MethodInfo m in typeof(Enumerable).GetMethods().Where(m => m.Name == "ToList"))
foreach (ParameterInfo p in m.GetParameters().Where(p => p.Name.Equals("source")))
if (p.ParameterType.GetGenericArguments().Count() == 1)
ToListMethod = (MethodInfo)p.Member;
foreach (MethodInfo m in typeof(Queryable).GetMethods().Where(m => m.Name == "AsQueryable"))
foreach (ParameterInfo p in m.GetParameters().Where(p => p.Name.Equals("source")))
if (p.ParameterType.GetGenericArguments().Count() == 1)
AsQueryableMethod = (MethodInfo)p.Member;
CreateMergeMethod = typeof(CopyToExt).GetMethods().First(m => m.Name == "CreateMergeStack");
AddMergeMethod = typeof(MergeStack).GetMethods().First(m => m.Name == "AddReturnOrCreateAddReturn");
TryCopyMethod = typeof(MergeStack).GetMethods().First(m => m.Name == "TryCopy");
}
public static IQueryable<TDest> CopyTo<TSrc, TDest>(this IQueryable<TSrc> queryable)
where TSrc : class, IEntity
where TDest : class, IEntity
{
var copyExpr = CreateTryCopy<TSrc, TDest>();
var ms = CreateMergeStack<TSrc>();
return queryable.Select(ms).Select(copyExpr);
}
public static IEnumerable<TDest> CopyTo<TSrc, TDest>(this IEnumerable<TSrc> queryable)
where TSrc : class, IEntity
where TDest : class, IEntity
{
return queryable.AsQueryable().CopyTo<TSrc, TDest>().AsEnumerable();
}
public static Expression<Func<TSrc, Stackholder<TSrc>>> CreateMergeStack<TSrc>()
{
return mergeStackExpr.GetOrAdd(typeof(TSrc), (type) =>
{
var shtype = typeof(Stackholder<TSrc>);
var parm = Expression.Parameter(typeof(TSrc));
var destNewExpr = Expression.New(shtype);
var methodcall = Expression.Call(null,
CopyToExt.AddMergeMethod);
var memInit = Expression.MemberInit(destNewExpr,
Expression.Bind(shtype.GetField("Src"), parm),
Expression.Bind(shtype.GetField("Ms"), methodcall));
return Expression.Lambda<Func<TSrc, Stackholder<TSrc>>>(memInit, parm);
}) as Expression<Func<TSrc, Stackholder<TSrc>>>;
}
public static Expression<Func<Stackholder<TSrc>, TDest>> CreateTryCopy<TSrc, TDest>()
{
var shtype = typeof(Stackholder<TSrc>);
var parentParam = Expression.Parameter(shtype);
var SrcExpr = Expression.PropertyOrField(parentParam, "Src");
var MSExpr = Expression.PropertyOrField(parentParam, "Ms");
var tcMethod = Expression.Call(MSExpr,
TryCopyMethod.MakeGenericMethod(new Type[] { typeof(TSrc), typeof(TDest) }),
SrcExpr);
return Expression.Lambda<Func<Stackholder<TSrc>, TDest>>(tcMethod, parentParam);
}
internal static bool Impliments(this Type type, Type inheritedType)
{
return (type.IsSubclassOf(inheritedType) || type.GetInterface(inheritedType.FullName) != null);
}
internal static bool Impliments<T>(this Type type, Type inheritedType = null)
{
return type.Impliments(typeof(T));
}
private static ConcurrentDictionary<Type, Object> AssignDict =
new ConcurrentDictionary<Type, Object>(new Dictionary<Type, Object>());
internal static Func<TSrc, TDest, MergeStack, TDest> Assign<TSrc, TDest>()
{
return (Func<TSrc, TDest, MergeStack, TDest>) AssignDict.GetOrAdd(typeof (Func<TSrc, TDest>), (indexType) =>
{
var tSrc = typeof (TSrc);
var tDest = typeof (TDest);
var srcEntityInterfaces = tSrc.GetInterfaces().Where(x => x.Impliments<IEntity>());
var destEntityInterfaces = tDest.GetInterfaces().Where(x => x.Impliments<IEntity>());
var srcParam = Expression.Parameter(tSrc);
var destParam = Expression.Parameter(tDest);
var MSExpr = Expression.Parameter(typeof (MergeStack));
var common = destEntityInterfaces.Intersect(srcEntityInterfaces);
var memberbindings = common.Where(x => x.Impliments<IEntityProperty>())
.Select(type => type.GetProperties().First())
.Select(
prop =>
Expression.Assign(Expression.Property(destParam, prop.Name),
Expression.Property(srcParam, prop.Name)))
.Cast<Expression>().ToList();
foreach (var type in common.Where(x => x.Impliments<IEntityObject>()))
{
var destSubType = destEntityInterfaces.First(x => x.Impliments(type))
.GetGenericArguments()
.First();
var srcSubType = srcEntityInterfaces.First(x => x.Impliments(type))
.GetGenericArguments()
.First();
var dProp = destEntityInterfaces.First(x => x.Impliments(type)).GetProperties().First();
var sProp = srcEntityInterfaces.First(x => x.Impliments(type)).GetProperties().First();
var tcParam = Expression.Parameter(srcSubType);
var tcMethod = Expression.Call(MSExpr,
TryCopyMethod.MakeGenericMethod(new Type[] {srcSubType, destSubType}),
tcParam);
LambdaExpression mergeLambda = Expression.Lambda(tcMethod, tcParam);
MemberExpression memberExpression = Expression.Property(srcParam, sProp.Name);
InvocationExpression invocationExpression = Expression.Invoke(mergeLambda,
Expression.Property(srcParam, sProp.Name));
var check = Expression.Condition(
Expression.MakeBinary(ExpressionType.NotEqual, memberExpression,
Expression.Constant(null, sProp.PropertyType)), invocationExpression,
Expression.Constant(null, invocationExpression.Type));
BinaryExpression binaryExpression = Expression.Assign(Expression.Property(destParam, dProp.Name),
check);
memberbindings.Add(binaryExpression);
}
foreach (var type in common.Where(x => x.Impliments<IEntityCollection>()))
{
var destSubType = destEntityInterfaces.First(x => x.Impliments(type))
.GetGenericArguments()
.First();
var srcSubType = srcEntityInterfaces.First(x => x.Impliments(type))
.GetGenericArguments()
.First();
var dProp = destEntityInterfaces.First(x => x.Impliments(type)).GetProperties().First();
var sProp = srcEntityInterfaces.First(x => x.Impliments(type)).GetProperties().First();
var tcParam = Expression.Parameter(srcSubType);
var tcMethod = Expression.Call(MSExpr,
TryCopyMethod.MakeGenericMethod(new Type[] {srcSubType, destSubType}),
tcParam);
LambdaExpression mergeLambda = Expression.Lambda(tcMethod, tcParam);
var memberExpression = Expression.Property(srcParam, sProp.Name);
var selectExpr = Expression.Call(null,
AsQueryableMethod.MakeGenericMethod(new Type[] {srcSubType}),
new Expression[] {memberExpression});
selectExpr = Expression.Call(null,
CopyToExt.SelectMethod.MakeGenericMethod(new Type[] {srcSubType, destSubType}),
new Expression[] {selectExpr, mergeLambda});
selectExpr = Expression.Call(null,
CopyToExt.ToListMethod.MakeGenericMethod(new Type[] {destSubType}),
new Expression[] {selectExpr});
var check = Expression.Condition(
Expression.MakeBinary(ExpressionType.NotEqual, memberExpression,
Expression.Constant(null, sProp.PropertyType)), selectExpr,
Expression.Constant(null, selectExpr.Type));
memberbindings.Add(Expression.Assign(Expression.Property(destParam, dProp.Name), check));
}
memberbindings.Add(destParam);
return
Expression.Lambda<Func<TSrc, TDest, MergeStack, TDest>>(Expression.Block(memberbindings),
new ParameterExpression[] {srcParam, destParam, MSExpr}).Compile();
});
}
}
public class Stackholder<TSrc>
{
public MergeStack Ms;
public TSrc Src;
}
public class MergeStack
{
private static ConcurrentDictionary<Thread, MergeStack> StackDict = new ConcurrentDictionary<Thread, MergeStack>(new Dictionary<Thread, MergeStack>());
private readonly Dictionary<Type, Dictionary<Object, Object>> _mergeObjDict = new Dictionary<Type, Dictionary<object, object>>();
public static MergeStack AddReturnOrCreateAddReturn()
{
return StackDict.GetOrAdd(Thread.CurrentThread, (x) => new MergeStack() { });
}
public TDest TryCopy<TSrc, TDest>(TSrc Src)
where TSrc : class, IEntity
where TDest : class, IEntity, new()
{
if (Src == null) return null;
var objToIndex = new TDest();
Dictionary<object, object> objToObj;
if (!_mergeObjDict.ContainsKey(objToIndex.GetType()))
{
objToObj = new Dictionary<object, object>();
_mergeObjDict.Add(objToIndex.GetType(), objToObj);
}
else
{
objToObj = _mergeObjDict[objToIndex.GetType()];
}
if (!objToObj.ContainsKey(Src))
{
objToObj.Add(Src, objToIndex);
return CopyToExt.Assign<TSrc, TDest>()(Src, objToIndex, this);
}
return objToObj[Src] as TDest;
}
}