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;

    }

}