public static T CloneObject <T>(T obj) { // this is faster than typeof(T).IsValueType if (obj is ValueType) { if (typeof(T) == obj.GetType()) { return(obj); } // we're here so, we clone value type obj as object type T // so, we need to copy it, bcs we have a reference, not real object. return((T)ShallowObjectCloner.CloneObject(obj)); } if (ReferenceEquals(obj, null)) { return((T)(object)null); } if (DeepClonerSafeTypes.CanReturnSameObject(obj.GetType())) { return(obj); } return((T)ShallowObjectCloner.CloneObject(obj)); }
private static object GenerateProcessArrayMethod(Type type, bool isDeep) { Type elementType = type.GetElementType(); int arrayRank = type.GetArrayRank(); ParameterExpression parameterExpression = Expression.Parameter(typeof(object)); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object)); ParameterExpression parameterExpression3 = Expression.Parameter(typeof(DeepCloneState)); Type delegateType = typeof(Func <, , ,>).MakeGenericType(typeof(object), typeof(object), typeof(DeepCloneState), typeof(object)); if (arrayRank == 1 && type == elementType.MakeArrayType()) { if (!isDeep) { MethodCallExpression body = Expression.Call(typeof(ClonerToExprGenerator).GetPrivateStaticMethod("ShallowClone1DimArraySafeInternal").MakeGenericMethod(elementType), Expression.Convert(parameterExpression, type), Expression.Convert(parameterExpression2, type)); return(Expression.Lambda(delegateType, body, parameterExpression, parameterExpression2, parameterExpression3).Compile()); } string methodName = "Clone1DimArrayClassInternal"; if (DeepClonerSafeTypes.CanNotCopyType(elementType, null)) { methodName = "Clone1DimArraySafeInternal"; } else if (elementType.IsValueType()) { methodName = "Clone1DimArrayStructInternal"; } MethodCallExpression body2 = Expression.Call(typeof(ClonerToExprGenerator).GetPrivateStaticMethod(methodName).MakeGenericMethod(elementType), Expression.Convert(parameterExpression, type), Expression.Convert(parameterExpression2, type), parameterExpression3); return(Expression.Lambda(delegateType, body2, parameterExpression, parameterExpression2, parameterExpression3).Compile()); } MethodCallExpression body3 = Expression.Call(typeof(ClonerToExprGenerator).GetPrivateStaticMethod((arrayRank == 2 && type == elementType.MakeArrayType()) ? "Clone2DimArrayInternal" : "CloneAbstractArrayInternal"), Expression.Convert(parameterExpression, type), Expression.Convert(parameterExpression2, type), parameterExpression3, Expression.Constant(isDeep)); return(Expression.Lambda(delegateType, body3, parameterExpression, parameterExpression2, parameterExpression3).Compile()); }
private static object CloneClassRoot(object obj) { if (obj == null) { return(null); } // we can receive an poco objects which is faster to copy in shallow way if possible var type = obj.GetType(); // 200ms if (DeepClonerSafeTypes.IsClassSafe(type)) { return(ShallowObjectCloner.CloneObject(obj)); } // 350ms var cloner = (Func <object, DeepCloneState, object>)DeepClonerCache.GetOrAddClass(type, t => GenerateCloner(t, true)); if (cloner == null) { return(obj); } // 200ms return(cloner(obj, new DeepCloneState())); }
private static object GenerateProcessArrayMethod(Type type) { Type elementType = type.GetElementType(); int arrayRank = type.GetArrayRank(); MethodInfo method; if (arrayRank != 1 || type != elementType.MakeArrayType()) { method = ((arrayRank != 2 || !(type == elementType.MakeArrayType())) ? typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneAbstractArrayInternal") : typeof(DeepClonerGenerator).GetPrivateStaticMethod("Clone2DimArrayInternal").MakeGenericMethod(elementType)); } else { string methodName = "Clone1DimArrayClassInternal"; if (DeepClonerSafeTypes.CanNotCopyType(elementType, null)) { methodName = "Clone1DimArraySafeInternal"; } else if (elementType.IsValueType()) { methodName = "Clone1DimArrayStructInternal"; } method = typeof(DeepClonerGenerator).GetPrivateStaticMethod(methodName).MakeGenericMethod(elementType); } ParameterExpression parameterExpression = Expression.Parameter(typeof(object)); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(DeepCloneState)); MethodCallExpression body = Expression.Call(method, Expression.Convert(parameterExpression, type), parameterExpression2); return(Expression.Lambda(typeof(Func <, ,>).MakeGenericType(typeof(object), typeof(DeepCloneState), typeof(object)), body, parameterExpression, parameterExpression2).Compile()); }
internal static object GenerateClonerInternal(Type realType, bool asObject) { if (DeepClonerSafeTypes.CanNotCopyType(realType, null)) { return(null); } return(GenerateProcessMethod(realType, asObject && realType.IsValueType())); }
internal static T[,] Clone2DimArrayInternal <T>(T[,] objFrom, T[,] objTo, DeepCloneState state, bool isDeep) { if (objFrom == null || objTo == null) { return(null); } int num = Math.Min(objFrom.GetLength(0), objTo.GetLength(0)); int num2 = Math.Min(objFrom.GetLength(1), objTo.GetLength(1)); state.AddKnownRef(objFrom, objTo); if ((!isDeep || DeepClonerSafeTypes.CanNotCopyType(typeof(T), null)) && objFrom.GetLength(0) == objTo.GetLength(0) && objFrom.GetLength(1) == objTo.GetLength(1)) { Array.Copy(objFrom, objTo, objFrom.Length); return(objTo); } if (!isDeep) { for (int i = 0; i < num; i++) { for (int j = 0; j < num2; j++) { int num3 = i; int num4 = j; T val = objFrom[i, j]; objTo[num3, num4] = val; } } return(objTo); } if (typeof(T).IsValueType()) { Func <T, DeepCloneState, T> clonerForValueType = DeepClonerGenerator.GetClonerForValueType <T>(); for (int k = 0; k < num; k++) { for (int l = 0; l < num2; l++) { int num5 = k; int num6 = l; T val2 = clonerForValueType(objFrom[k, l], state); objTo[num5, num6] = val2; } } } else { for (int m = 0; m < num; m++) { for (int n = 0; n < num2; n++) { int num7 = m; int num8 = n; T obj = (T)DeepClonerGenerator.CloneClassInternal(objFrom[m, n], state); objTo[num7, num8] = obj; } } } return(objTo); }
internal static T[,] Clone2DimArrayInternal <T>(T[,] objFrom, T[,] objTo, DeepCloneState state, bool isDeep) { // not null from called method, but will check it anyway if (objFrom == null || objTo == null) { return(null); } var l1 = Math.Min(objFrom.GetLength(0), objTo.GetLength(0)); var l2 = Math.Min(objFrom.GetLength(1), objTo.GetLength(1)); state.AddKnownRef(objFrom, objTo); if ((!isDeep || DeepClonerSafeTypes.CanReturnSameObject(typeof(T))) && objFrom.GetLength(0) == objTo.GetLength(0) && objFrom.GetLength(1) == objTo.GetLength(1)) { Array.Copy(objFrom, objTo, objFrom.Length); return(objTo); } if (!isDeep) { for (var i = 0; i < l1; i++) { for (var k = 0; k < l2; k++) { objTo[i, k] = objFrom[i, k]; } } return(objTo); } if (typeof(T).IsValueType()) { var cloner = DeepClonerGenerator.GetClonerForValueType <T>(); for (var i = 0; i < l1; i++) { for (var k = 0; k < l2; k++) { objTo[i, k] = cloner(objFrom[i, k], state); } } } else { for (var i = 0; i < l1; i++) { for (var k = 0; k < l2; k++) { objTo[i, k] = (T)DeepClonerGenerator.CloneClassInternal(objFrom[i, k], state); } } } return(objTo); }
internal static T[,] Clone2DimArrayInternal <T>(T[,] obj, DeepCloneState state) { if (obj == null) { return(null); } int length = obj.GetLength(0); int length2 = obj.GetLength(1); T[,] array = new T[length, length2]; state.AddKnownRef(obj, array); if (DeepClonerSafeTypes.CanNotCopyType(typeof(T), null)) { Array.Copy(obj, array, obj.Length); return(array); } if (typeof(T).IsValueType()) { Func <T, DeepCloneState, T> clonerForValueType = GetClonerForValueType <T>(); for (int i = 0; i < length; i++) { for (int j = 0; j < length2; j++) { T[,] array2 = array; int num = i; int num2 = j; T val = clonerForValueType(obj[i, j], state); array2[num, num2] = val; } } } else { for (int k = 0; k < length; k++) { for (int l = 0; l < length2; l++) { T[,] array3 = array; int num3 = k; int num4 = l; T obj2 = (T)CloneClassInternal(obj[k, l], state); array3[num3, num4] = obj2; } } } return(array); }
private static object GenerateProcessArrayMethod(Type type, bool isDeep) { var elementType = type.GetElementType(); var rank = type.GetArrayRank(); ParameterExpression from = Expression.Parameter(typeof(object)); ParameterExpression to = Expression.Parameter(typeof(object)); var state = Expression.Parameter(typeof(DeepCloneState)); var funcType = typeof(Func <, , ,>).MakeGenericType(typeof(object), typeof(object), typeof(DeepCloneState), typeof(object)); if (rank == 1 && type == elementType.MakeArrayType()) { if (!isDeep) { var callS = Expression.Call( typeof(ClonerToExprGenerator).GetPrivateStaticMethod("ShallowClone1DimArraySafeInternal") .MakeGenericMethod(elementType), Expression.Convert(from, type), Expression.Convert(to, type)); return(Expression.Lambda(funcType, callS, from, to, state).Compile()); } else { var methodName = "Clone1DimArrayClassInternal"; if (DeepClonerSafeTypes.CanReturnSameObject(elementType)) { methodName = "Clone1DimArraySafeInternal"; } else if (elementType.IsValueType()) { methodName = "Clone1DimArrayStructInternal"; } var methodInfo = typeof(ClonerToExprGenerator).GetPrivateStaticMethod(methodName).MakeGenericMethod(elementType); var callS = Expression.Call(methodInfo, Expression.Convert(from, type), Expression.Convert(to, type), state); return(Expression.Lambda(funcType, callS, from, to, state).Compile()); } } else { // multidim or not zero-based arrays var methodInfo = typeof(ClonerToExprGenerator).GetPrivateStaticMethod( rank == 2 && type == elementType.MakeArrayType() ? "Clone2DimArrayInternal" : "CloneAbstractArrayInternal"); var callS = Expression.Call(methodInfo, Expression.Convert(from, type), Expression.Convert(to, type), state, Expression.Constant(isDeep)); return(Expression.Lambda(funcType, callS, from, to, state).Compile()); } }
public static T CloneObject <T>(T obj) { if (obj is ValueType) { var type = obj.GetType(); if (typeof(T) == type) { if (DeepClonerSafeTypes.CanReturnSameObject(type)) { return(obj); } return(CloneStructInternal(obj, new DeepCloneState())); } } return((T)CloneClassRoot(obj)); }
private static object GenerateProcessArrayMethod(Type type) { var elementType = type.GetElementType(); var rank = type.GetArrayRank(); MethodInfo methodInfo; // multidim or not zero-based arrays if (rank != 1 || type != elementType.MakeArrayType()) { if (rank == 2 && type == elementType.MakeArrayType()) { // small optimization for 2 dim arrays methodInfo = typeof(DeepClonerGenerator).GetPrivateStaticMethod("Clone2DimArrayInternal").MakeGenericMethod(elementType); } else { methodInfo = typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneAbstractArrayInternal"); } } else { var methodName = "Clone1DimArrayClassInternal"; if (DeepClonerSafeTypes.IsTypeSafe(elementType, null)) { methodName = "Clone1DimArraySafeInternal"; } else if (elementType.IsValueType()) { methodName = "Clone1DimArrayStructInternal"; } methodInfo = typeof(DeepClonerGenerator).GetPrivateStaticMethod(methodName).MakeGenericMethod(elementType); } ParameterExpression from = Expression.Parameter(typeof(object)); var state = Expression.Parameter(typeof(DeepCloneState)); var call = Expression.Call(methodInfo, Expression.Convert(from, type), state); var funcType = typeof(Func <, ,>).MakeGenericType(typeof(object), typeof(DeepCloneState), typeof(object)); return(Expression.Lambda(funcType, call, from, state).Compile()); }
// relatively frequent case. specially handled internal static T[,] Clone2DimArrayInternal <T>(T[,] obj, DeepCloneState state) { // not null from called method, but will check it anyway if (obj == null) { return(null); } var l1 = obj.GetLength(0); var l2 = obj.GetLength(1); var outArray = new T[l1, l2]; state.AddKnownRef(obj, outArray); if (DeepClonerSafeTypes.IsTypeSafe(typeof(T), null)) { Array.Copy(obj, outArray, obj.Length); return(outArray); } if (typeof(T).IsValueType()) { var cloner = GetClonerForValueType <T>(); for (var i = 0; i < l1; i++) { for (var k = 0; k < l2; k++) { outArray[i, k] = cloner(obj[i, k], state); } } } else { for (var i = 0; i < l1; i++) { for (var k = 0; k < l2; k++) { outArray[i, k] = (T)CloneClassInternal(obj[i, k], state); } } } return(outArray); }
private static object CloneClassRoot(object obj) { if (obj == null) { return(null); } Type type = obj.GetType(); if (DeepClonerSafeTypes.CanNotDeepCopyClass(type)) { return(ShallowObjectCloner.CloneObject(obj)); } Func <object, DeepCloneState, object> func = (Func <object, DeepCloneState, object>)DeepClonerCache.GetOrAddClass(type, (Type t) => GenerateCloner(t, true)); if (func == null) { return(obj); } return(func(obj, new DeepCloneState())); }
private static object GenerateCloner(Type t, bool asObject) { if (DeepClonerSafeTypes.CanReturnSameObject(t) && (asObject && !t.IsValueType())) { return(null); } #if !NETCORE if (ShallowObjectCloner.IsSafeVariant()) { return(DeepClonerExprGenerator.GenerateClonerInternal(t, asObject)); } else { return(DeepClonerMsilGenerator.GenerateClonerInternal(t, asObject)); } #else return(DeepClonerExprGenerator.GenerateClonerInternal(t, asObject)); #endif }
private static object GenerateProcessMethod(Type type, bool unboxStruct) { if (type.IsArray) { return(GenerateProcessArrayMethod(type)); } var methodType = unboxStruct || type.IsClass() ? typeof(object) : type; var expressionList = new List <Expression>(); ParameterExpression from = Expression.Parameter(methodType); var fromLocal = from; var toLocal = Expression.Variable(type); var state = Expression.Parameter(typeof(DeepCloneState)); if (!type.IsValueType()) { var methodInfo = typeof(object).GetPrivateMethod("MemberwiseClone"); // to = (T)from.MemberwiseClone() expressionList.Add(Expression.Assign(toLocal, Expression.Convert(Expression.Call(from, methodInfo), type))); fromLocal = Expression.Variable(type); // fromLocal = (T)from expressionList.Add(Expression.Assign(fromLocal, Expression.Convert(from, type))); // added from -> to binding to ensure reference loop handling // structs cannot loop here // state.AddKnownRef(from, to) expressionList.Add(Expression.Call(state, typeof(DeepCloneState).GetMethod("AddKnownRef"), from, toLocal)); } else { if (unboxStruct) { // toLocal = (T)from; expressionList.Add(Expression.Assign(toLocal, Expression.Unbox(from, type))); fromLocal = Expression.Variable(type); // fromLocal = toLocal; // structs, it is ok to copy expressionList.Add(Expression.Assign(fromLocal, toLocal)); } else { // toLocal = from expressionList.Add(Expression.Assign(toLocal, from)); } } List <FieldInfo> fi = new List <FieldInfo>(); var tp = type; do { #if !NETCORE // don't do anything with this dark magic! if (tp == typeof(ContextBoundObject)) { break; } #else if (tp.Name == "ContextBoundObject") { break; } #endif fi.AddRange(tp.GetDeclaredFields()); tp = tp.BaseType(); }while (tp != null); foreach (var fieldInfo in fi) { if (!DeepClonerSafeTypes.IsTypeSafe(fieldInfo.FieldType, null)) { var methodInfo = fieldInfo.FieldType.IsValueType() ? typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneStructInternal") .MakeGenericMethod(fieldInfo.FieldType) : typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneClassInternal"); var get = Expression.Field(fromLocal, fieldInfo); // toLocal.Field = Clone...Internal(fromLocal.Field) var call = (Expression)Expression.Call(methodInfo, get, state); if (!fieldInfo.FieldType.IsValueType()) { call = Expression.Convert(call, fieldInfo.FieldType); } // should handle specially // todo: think about optimization, but it rare case if (fieldInfo.IsInitOnly) { // var setMethod = fieldInfo.GetType().GetMethod("SetValue", new[] { typeof(object), typeof(object) }); // expressionList.Add(Expression.Call(Expression.Constant(fieldInfo), setMethod, toLocal, call)); var setMethod = typeof(DeepClonerExprGenerator).GetPrivateStaticMethod("ForceSetField"); expressionList.Add(Expression.Call(setMethod, Expression.Constant(fieldInfo), Expression.Convert(toLocal, typeof(object)), Expression.Convert(call, typeof(object)))); } else { expressionList.Add(Expression.Assign(Expression.Field(toLocal, fieldInfo), call)); } } } expressionList.Add(Expression.Convert(toLocal, methodType)); var funcType = typeof(Func <, ,>).MakeGenericType(methodType, typeof(DeepCloneState), methodType); var blockParams = new List <ParameterExpression>(); if (from != fromLocal) { blockParams.Add(fromLocal); } blockParams.Add(toLocal); return(Expression.Lambda(funcType, Expression.Block(blockParams, expressionList), from, state).Compile()); }
private static object GenerateProcessMethod(Type type, bool unboxStruct) { if (type.IsArray) { return(GenerateProcessArrayMethod(type)); } if (type.FullName != null && type.FullName.StartsWith("System.Tuple`")) { // if not safe type it is no guarantee that some type will contain reference to // this tuple. In usual way, we're creating new object, setting reference for it // and filling data. For tuple, we will fill data before creating object // (in constructor arguments) var genericArguments = type.GenericArguments(); // current tuples contain only 8 arguments, but may be in future... // we'll write code that works with it if (genericArguments.Length < 10 && genericArguments.All(DeepClonerSafeTypes.CanReturnSameObject)) { return(GenerateProcessTupleMethod(type)); } } var methodType = unboxStruct || type.IsClass() ? typeof(object) : type; var expressionList = new List <Expression>(); ParameterExpression from = Expression.Parameter(methodType); var fromLocal = from; var toLocal = Expression.Variable(type); var state = Expression.Parameter(typeof(DeepCloneState)); if (!type.IsValueType()) { var methodInfo = typeof(object).GetPrivateMethod("MemberwiseClone"); // to = (T)from.MemberwiseClone() expressionList.Add(Expression.Assign(toLocal, Expression.Convert(Expression.Call(from, methodInfo), type))); fromLocal = Expression.Variable(type); // fromLocal = (T)from expressionList.Add(Expression.Assign(fromLocal, Expression.Convert(from, type))); // added from -> to binding to ensure reference loop handling // structs cannot loop here // state.AddKnownRef(from, to) expressionList.Add(Expression.Call(state, typeof(DeepCloneState).GetMethod("AddKnownRef"), from, toLocal)); } else { if (unboxStruct) { // toLocal = (T)from; expressionList.Add(Expression.Assign(toLocal, Expression.Unbox(from, type))); fromLocal = Expression.Variable(type); // fromLocal = toLocal; // structs, it is ok to copy expressionList.Add(Expression.Assign(fromLocal, toLocal)); } else { // toLocal = from expressionList.Add(Expression.Assign(toLocal, from)); } } List <FieldInfo> fi = new List <FieldInfo>(); var tp = type; do { #if !NETCORE // don't do anything with this dark magic! if (tp == typeof(ContextBoundObject)) { break; } #else if (tp.Name == "ContextBoundObject") { break; } #endif fi.AddRange(tp.GetDeclaredFields()); tp = tp.BaseType(); }while (tp != null); foreach (var fieldInfo in fi) { if (!DeepClonerSafeTypes.CanReturnSameObject(fieldInfo.FieldType)) { var methodInfo = fieldInfo.FieldType.IsValueType() ? typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneStructInternal") .MakeGenericMethod(fieldInfo.FieldType) : typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneClassInternal"); var get = Expression.Field(fromLocal, fieldInfo); // toLocal.Field = Clone...Internal(fromLocal.Field) var call = (Expression)Expression.Call(methodInfo, get, state); if (!fieldInfo.FieldType.IsValueType()) { call = Expression.Convert(call, fieldInfo.FieldType); } // should handle specially // todo: think about optimization, but it rare case if (fieldInfo.IsInitOnly) { // var setMethod = fieldInfo.GetType().GetMethod("SetValue", new[] { typeof(object), typeof(object) }); // expressionList.Add(Expression.Call(Expression.Constant(fieldInfo), setMethod, toLocal, call)); var setMethod = typeof(DeepClonerExprGenerator).GetPrivateStaticMethod("ForceSetField"); expressionList.Add(Expression.Call(setMethod, Expression.Constant(fieldInfo), Expression.Convert(toLocal, typeof(object)), Expression.Convert(call, typeof(object)))); } else { expressionList.Add(Expression.Assign(Expression.Field(toLocal, fieldInfo), call)); } } } expressionList.Add(Expression.Convert(toLocal, methodType)); var funcType = typeof(Func <, ,>).MakeGenericType(methodType, typeof(DeepCloneState), methodType); var blockParams = new List <ParameterExpression>(); if (from != fromLocal) { blockParams.Add(fromLocal); } blockParams.Add(toLocal); return(Expression.Lambda(funcType, Expression.Block(blockParams, expressionList), from, state).Compile()); }
private static object GenerateProcessMethod(Type type, bool isDeepClone) { if (type.IsArray) { return(GenerateProcessArrayMethod(type, isDeepClone)); } Type typeFromHandle = typeof(object); List <Expression> list = new List <Expression>(); ParameterExpression parameterExpression = Expression.Parameter(typeFromHandle); ParameterExpression parameterExpression2 = parameterExpression; ParameterExpression parameterExpression3 = Expression.Parameter(typeFromHandle); ParameterExpression parameterExpression4 = parameterExpression3; ParameterExpression parameterExpression5 = Expression.Parameter(typeof(DeepCloneState)); parameterExpression2 = Expression.Variable(type); parameterExpression4 = Expression.Variable(type); list.Add(Expression.Assign(parameterExpression2, Expression.Convert(parameterExpression, type))); list.Add(Expression.Assign(parameterExpression4, Expression.Convert(parameterExpression3, type))); if (isDeepClone) { list.Add(Expression.Call(parameterExpression5, typeof(DeepCloneState).GetMethod("AddKnownRef"), parameterExpression, parameterExpression3)); } List <FieldInfo> list2 = new List <FieldInfo>(); Type type2 = type; while (!(type2.Name == "ContextBoundObject")) { list2.AddRange(type2.GetDeclaredFields()); type2 = type2.BaseType(); if (!(type2 != (Type)null)) { break; } } foreach (FieldInfo item in list2) { if (isDeepClone && !DeepClonerSafeTypes.CanNotCopyType(item.FieldType, null)) { MethodInfo method = item.FieldType.IsValueType() ? typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneStructInternal").MakeGenericMethod(item.FieldType) : typeof(DeepClonerGenerator).GetPrivateStaticMethod("CloneClassInternal"); MemberExpression arg = Expression.Field(parameterExpression2, item); Expression expression = Expression.Call(method, arg, parameterExpression5); if (!item.FieldType.IsValueType()) { expression = Expression.Convert(expression, item.FieldType); } if (item.IsInitOnly) { MethodInfo privateStaticMethod = typeof(DeepClonerExprGenerator).GetPrivateStaticMethod("ForceSetField"); list.Add(Expression.Call(privateStaticMethod, Expression.Constant(item), Expression.Convert(parameterExpression4, typeof(object)), Expression.Convert(expression, typeof(object)))); } else { list.Add(Expression.Assign(Expression.Field(parameterExpression4, item), expression)); } } else { list.Add(Expression.Assign(Expression.Field(parameterExpression4, item), Expression.Field(parameterExpression2, item))); } } list.Add(Expression.Convert(parameterExpression4, typeFromHandle)); Type delegateType = typeof(Func <, , ,>).MakeGenericType(typeFromHandle, typeFromHandle, typeof(DeepCloneState), typeFromHandle); List <ParameterExpression> list3 = new List <ParameterExpression>(); if (parameterExpression != parameterExpression2) { list3.Add(parameterExpression2); } if (parameterExpression3 != parameterExpression4) { list3.Add(parameterExpression4); } return(Expression.Lambda(delegateType, Expression.Block(list3, list), parameterExpression, parameterExpression3, parameterExpression5).Compile()); }