├── .gitignore ├── DeepCopier.sln ├── LICENSE ├── README.md ├── src └── DeepCopier │ ├── Copier.cs │ ├── Copier`2.cs │ ├── DeepCopier.csproj │ ├── EnumerableCopier.cs │ ├── UnsupportedTypeException.cs │ └── Utils.cs └── test └── DeepCopier.Test ├── DeepCopier.Test.csproj ├── DeepCopyTest.cs └── TestClasses ├── ClassA.cs ├── ClassB.cs ├── ClassC.cs ├── ClassD.cs ├── ClassE.cs └── ClassF.cs /.gitignore: -------------------------------------------------------------------------------- 1 | /.vs 2 | /test/obj 3 | /test/bin 4 | /src/DeepCopier/obj 5 | /src/DeepCopier/bin 6 | /src/DeepCopier/.vs/DeepCopier/v15/*.suo 7 | /test/DeepCopier.Test/bin 8 | /test/DeepCopier.Test/obj 9 | -------------------------------------------------------------------------------- /DeepCopier.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26124.0 5 | MinimumVisualStudioVersion = 15.0.26124.0 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{62260C59-358E-4C17-9145-AA3B1AC76099}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{CD795DF8-F62B-45CB-A95E-35C525EB29BE}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeepCopier", "src\DeepCopier\DeepCopier.csproj", "{43156AAF-7A59-41AB-962B-D41875F7BC70}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeepCopier.Test", "test\DeepCopier.Test\DeepCopier.Test.csproj", "{CA75E336-31D2-4D66-8105-F32BAC26EB1C}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Debug|x64 = Debug|x64 18 | Debug|x86 = Debug|x86 19 | Release|Any CPU = Release|Any CPU 20 | Release|x64 = Release|x64 21 | Release|x86 = Release|x86 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {43156AAF-7A59-41AB-962B-D41875F7BC70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {43156AAF-7A59-41AB-962B-D41875F7BC70}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {43156AAF-7A59-41AB-962B-D41875F7BC70}.Debug|x64.ActiveCfg = Debug|Any CPU 27 | {43156AAF-7A59-41AB-962B-D41875F7BC70}.Debug|x64.Build.0 = Debug|Any CPU 28 | {43156AAF-7A59-41AB-962B-D41875F7BC70}.Debug|x86.ActiveCfg = Debug|Any CPU 29 | {43156AAF-7A59-41AB-962B-D41875F7BC70}.Debug|x86.Build.0 = Debug|Any CPU 30 | {43156AAF-7A59-41AB-962B-D41875F7BC70}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {43156AAF-7A59-41AB-962B-D41875F7BC70}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {43156AAF-7A59-41AB-962B-D41875F7BC70}.Release|x64.ActiveCfg = Release|Any CPU 33 | {43156AAF-7A59-41AB-962B-D41875F7BC70}.Release|x64.Build.0 = Release|Any CPU 34 | {43156AAF-7A59-41AB-962B-D41875F7BC70}.Release|x86.ActiveCfg = Release|Any CPU 35 | {43156AAF-7A59-41AB-962B-D41875F7BC70}.Release|x86.Build.0 = Release|Any CPU 36 | {CA75E336-31D2-4D66-8105-F32BAC26EB1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {CA75E336-31D2-4D66-8105-F32BAC26EB1C}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {CA75E336-31D2-4D66-8105-F32BAC26EB1C}.Debug|x64.ActiveCfg = Debug|Any CPU 39 | {CA75E336-31D2-4D66-8105-F32BAC26EB1C}.Debug|x64.Build.0 = Debug|Any CPU 40 | {CA75E336-31D2-4D66-8105-F32BAC26EB1C}.Debug|x86.ActiveCfg = Debug|Any CPU 41 | {CA75E336-31D2-4D66-8105-F32BAC26EB1C}.Debug|x86.Build.0 = Debug|Any CPU 42 | {CA75E336-31D2-4D66-8105-F32BAC26EB1C}.Release|Any CPU.ActiveCfg = Release|Any CPU 43 | {CA75E336-31D2-4D66-8105-F32BAC26EB1C}.Release|Any CPU.Build.0 = Release|Any CPU 44 | {CA75E336-31D2-4D66-8105-F32BAC26EB1C}.Release|x64.ActiveCfg = Release|Any CPU 45 | {CA75E336-31D2-4D66-8105-F32BAC26EB1C}.Release|x64.Build.0 = Release|Any CPU 46 | {CA75E336-31D2-4D66-8105-F32BAC26EB1C}.Release|x86.ActiveCfg = Release|Any CPU 47 | {CA75E336-31D2-4D66-8105-F32BAC26EB1C}.Release|x86.Build.0 = Release|Any CPU 48 | EndGlobalSection 49 | GlobalSection(SolutionProperties) = preSolution 50 | HideSolutionNode = FALSE 51 | EndGlobalSection 52 | GlobalSection(NestedProjects) = preSolution 53 | {43156AAF-7A59-41AB-962B-D41875F7BC70} = {62260C59-358E-4C17-9145-AA3B1AC76099} 54 | {CA75E336-31D2-4D66-8105-F32BAC26EB1C} = {CD795DF8-F62B-45CB-A95E-35C525EB29BE} 55 | EndGlobalSection 56 | GlobalSection(ExtensibilityGlobals) = postSolution 57 | SolutionGuid = {0FCFB83A-5BD4-4019-85BA-FF0E274200C3} 58 | EndGlobalSection 59 | EndGlobal 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 772552754@qq.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DeepCopier 2 | 3 | DeepCopier is a small library that can deep copy object by Expression Tree. 4 | 5 | ## Installation: 6 | Install DeepCopier [NuGet package](https://www.nuget.org/packages/DeepCopier/). 7 | 8 | ## Usage Examples: 9 | 10 | ### 1.Deep copy the source object. 11 | ```C# 12 | SomeType obj1 = new SomeType(); 13 | SomeType obj2 = Copier.Copy(obj1); 14 | 15 | List list1 = new List{ obj1 }; 16 | List list2 = Copier.Copy(list1); 17 | ``` 18 | 19 | ### 2.Create a new instance of the target type, and deep copy the property values of the given source object into the target instance. 20 | ```C# 21 | /* The source and target classes do not have to match or even be derived 22 | from each other, as long as the properties match. */ 23 | SomeType obj1 = new SomeType(); 24 | AnotherType obj2 = Copier.Copy(obj1); 25 | ``` 26 | 27 | ### 3.Copy the property values of the given source object into an existing target object. 28 | ```C# 29 | /* The source and target classes do not have to match or even be derived 30 | from each other, as long as the properties match. */ 31 | SomeType obj1 = new SomeType(); 32 | AnotherType obj2 = new AnotherType(); 33 | Copier.Copy(obj1, obj2); 34 | ``` 35 | -------------------------------------------------------------------------------- /src/DeepCopier/Copier.cs: -------------------------------------------------------------------------------- 1 | namespace DeepCopier 2 | { 3 | /// 4 | /// The class that can deep copy object by Expression Tree 5 | /// 利用表达式树实现深拷贝的类 6 | /// 7 | public static class Copier 8 | { 9 | /// 10 | /// Create a new instance of the target type, 11 | /// and deep copy the property values of the given source object into the target instance 12 | /// 新建目标类型实例,并将源对象的属性值拷贝至目标对象的对应属性 13 | /// 14 | /// The type of source object 源对象类型 15 | /// The type of target object 目标对象类型 16 | /// The source object 源对象实例 17 | /// 18 | /// A new instance of the target type 19 | /// 深拷贝了源对象属性的目标对象实例 20 | /// 21 | public static TTarget Copy(TSource source) 22 | => Copier.Copy(source); 23 | 24 | /// 25 | /// Deep copy the source object 26 | /// 对源对象进行深拷贝 27 | /// 28 | /// The type of source obejct 对象类型 29 | /// The source obejct 源对象 30 | /// 31 | /// A deep copied instance of source obejct 32 | /// 深拷贝的对象实例 33 | /// 34 | public static T Copy(T source) => Copier.Copy(source); 35 | 36 | /// 37 | /// Copy the property values of the given source object into the existing target object 38 | /// 将源对象的属性值拷贝至已存在的目标对象的对应属性 39 | /// 40 | /// The type of source object 源对象类型 41 | /// The type of target object 目标对象类型 42 | /// The source object 源对象实例 43 | /// The target object 目标对象实例 44 | public static void Copy(TSource source, TTarget target) 45 | => Copier.Copy(source, target); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/DeepCopier/Copier`2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using System.Reflection; 5 | 6 | namespace DeepCopier 7 | { 8 | /// 9 | /// 利用表达式树实现深拷贝的类 10 | /// 11 | /// 源对象类型 12 | /// 目标对象类型 13 | internal static class Copier 14 | { 15 | // 缓存委托 16 | private static Func _copyFunc; 17 | private static Action _copyAction; 18 | 19 | /// 20 | /// 新建目标类型实例,并将源对象的属性值拷贝至目标对象的对应属性 21 | /// 22 | /// 源对象实例 23 | /// 深拷贝了源对象属性的目标对象实例 24 | public static TTarget Copy(TSource source) 25 | { 26 | if (source == null) return default(TTarget); 27 | 28 | // 因为对于泛型类型而言,每次传入不同的泛型参数都会调用静态构造函数,所以可以通过这种方式进行缓存 29 | if (_copyFunc != null) 30 | { 31 | // 如果之前缓存过,则直接调用缓存的委托 32 | return _copyFunc(source); 33 | } 34 | 35 | Type sourceType = typeof(TSource); 36 | Type targetType = typeof(TTarget); 37 | 38 | var paramExpr = Expression.Parameter(sourceType, nameof(source)); 39 | 40 | Expression bodyExpr; 41 | 42 | // 如果对象可以遍历(目前只支持数组和ICollection实现类) 43 | if (sourceType == targetType && Utils.IsIEnumerableExceptString(sourceType)) 44 | { 45 | bodyExpr = Expression.Call(null, EnumerableCopier.GetMethondInfo(sourceType), paramExpr); 46 | } 47 | else 48 | { 49 | var memberBindings = new List(); 50 | // 遍历目标对象的所有属性信息 51 | foreach (var targetPropInfo in targetType.GetProperties()) 52 | { 53 | // 从源对象获取同名的属性信息 54 | var sourcePropInfo = sourceType.GetProperty(targetPropInfo.Name); 55 | 56 | Type sourcePropType = sourcePropInfo?.PropertyType; 57 | Type targetPropType = targetPropInfo.PropertyType; 58 | 59 | // 只在满足以下三个条件的情况下进行拷贝 60 | // 1.源属性类型和目标属性类型一致 61 | // 2.源属性可读 62 | // 3.目标属性可写 63 | if (sourcePropType == targetPropType 64 | && sourcePropInfo.CanRead 65 | && targetPropInfo.CanWrite) 66 | { 67 | // 获取属性值的表达式 68 | Expression expression = Expression.Property(paramExpr, sourcePropInfo); 69 | 70 | // 如果目标属性是值类型或者字符串,则直接做赋值处理 71 | // 暂不考虑目标值类型有非字符串的引用类型这种特殊情况 72 | // 非字符串引用类型做递归处理 73 | if (Utils.IsRefTypeExceptString(targetPropType)) 74 | { 75 | // 进行递归 76 | if (Utils.IsRefTypeExceptString(targetPropType)) 77 | { 78 | expression = Expression.Call(null, 79 | GetCopyMethodInfo(sourcePropType, targetPropType), expression); 80 | } 81 | } 82 | memberBindings.Add(Expression.Bind(targetPropInfo, expression)); 83 | } 84 | } 85 | 86 | bodyExpr = Expression.MemberInit(Expression.New(targetType), memberBindings); 87 | } 88 | 89 | var lambdaExpr 90 | = Expression.Lambda>(bodyExpr, paramExpr); 91 | 92 | _copyFunc = lambdaExpr.Compile(); 93 | return _copyFunc(source); 94 | } 95 | 96 | /// 97 | /// 新建目标类型实例,并将源对象的属性值拷贝至目标对象的对应属性 98 | /// 99 | /// 源对象实例 100 | /// 目标对象实例 101 | public static void Copy(TSource source, TTarget target) 102 | { 103 | if (source == null) return; 104 | 105 | // 因为对于泛型类型而言,每次传入不同的泛型参数都会调用静态构造函数,所以可以通过这种方式进行缓存 106 | // 如果之前缓存过,则直接调用缓存的委托 107 | if (_copyAction != null) 108 | { 109 | _copyAction(source, target); 110 | return; 111 | } 112 | 113 | Type sourceType = typeof(TSource); 114 | Type targetType = typeof(TTarget); 115 | 116 | // 如果双方都可以被遍历 117 | if (Utils.IsIEnumerableExceptString(sourceType) && Utils.IsIEnumerableExceptString(targetType)) 118 | { 119 | // TODO 120 | // 向已存在的数组或者ICollection拷贝的功能暂不支持 121 | } 122 | else 123 | { 124 | var paramSourceExpr = Expression.Parameter(sourceType, nameof(source)); 125 | var paramTargetExpr = Expression.Parameter(targetType, nameof(target)); 126 | 127 | var binaryExpressions = new List(); 128 | // 遍历目标对象的所有属性信息 129 | foreach (var targetPropInfo in targetType.GetProperties()) 130 | { 131 | // 从源对象获取同名的属性信息 132 | var sourcePropInfo = sourceType.GetProperty(targetPropInfo.Name); 133 | 134 | Type sourcePropType = sourcePropInfo?.PropertyType; 135 | Type targetPropType = targetPropInfo.PropertyType; 136 | 137 | // 只在满足以下三个条件的情况下进行拷贝 138 | // 1.源属性类型和目标属性类型一致 139 | // 2.源属性可读 140 | // 3.目标属性可写 141 | if (sourcePropType == targetPropType 142 | && sourcePropInfo.CanRead 143 | && targetPropInfo.CanWrite) 144 | { 145 | // 获取属性值的表达式 146 | Expression expression = Expression.Property(paramSourceExpr, sourcePropInfo); 147 | Expression targetPropExpr = Expression.Property(paramTargetExpr, targetPropInfo); 148 | 149 | // 如果目标属性是值类型或者字符串,则直接做赋值处理 150 | // 暂不考虑目标值类型有非字符串的引用类型这种特殊情况 151 | if (Utils.IsRefTypeExceptString(targetPropType)) 152 | { 153 | expression = Expression.Call(null, 154 | GetCopyMethodInfo(sourcePropType, targetPropType), expression); 155 | } 156 | binaryExpressions.Add(Expression.Assign(targetPropExpr, expression)); 157 | } 158 | } 159 | 160 | Expression bodyExpr = Expression.Block(binaryExpressions); 161 | 162 | var lambdaExpr 163 | = Expression.Lambda>(bodyExpr, paramSourceExpr, paramTargetExpr); 164 | 165 | _copyAction = lambdaExpr.Compile(); 166 | _copyAction(source, target); 167 | } 168 | 169 | } 170 | 171 | private static MethodInfo GetCopyMethodInfo(Type source, Type target) 172 | => typeof(Copier<,>).MakeGenericType(source, target).GetMethod(nameof(Copy), new[] { source }); 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/DeepCopier/DeepCopier.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net45;netstandard2.0 5 | https://github.com/blurhkh/DeepCopier 6 | https://github.com/blurhkh/DeepCopier/blob/master/LICENSE 7 | blurhkh, 2018 8 | blurhkh 9 | DeepCopier 10 | 1.0.4 11 | A small and efficient library that can deep copy object by Expression Tree 12 | bin\Debug\netstandard2.0\DeepCopier.xml 13 | true 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/DeepCopier/EnumerableCopier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | namespace DeepCopier 6 | { 7 | /// 8 | /// 可遍历类型拷贝器 9 | /// 10 | internal class EnumerableCopier 11 | { 12 | private static readonly MethodInfo _copyArrayMethodInfo; 13 | 14 | private static readonly MethodInfo _copyICollectionMethodInfo; 15 | 16 | private static readonly Type _typeICollection = typeof(ICollection<>); 17 | 18 | static EnumerableCopier() 19 | { 20 | Type type = typeof(EnumerableCopier); 21 | _copyArrayMethodInfo = type.GetMethod(nameof(CopyArray)); 22 | _copyICollectionMethodInfo = type.GetMethod(nameof(CopyICollection)); 23 | } 24 | 25 | /// 26 | /// 根据IEnumerable的实现类类型选择合适的拷贝方法 27 | /// 28 | /// IEnumerable的实现类类型 29 | /// 拷贝方法信息 30 | public static MethodInfo GetMethondInfo(Type type) 31 | { 32 | if (type.IsArray) 33 | { 34 | return _copyArrayMethodInfo.MakeGenericMethod(type.GetElementType()); 35 | } 36 | else if (type.GetGenericArguments().Length > 0) 37 | { 38 | Type elementType = type.GetGenericArguments()[0]; 39 | if (_typeICollection.MakeGenericType(elementType).IsAssignableFrom(type)) 40 | { 41 | return _copyICollectionMethodInfo.MakeGenericMethod(type, elementType); 42 | 43 | } 44 | } 45 | throw new UnsupportedTypeException(type); 46 | } 47 | 48 | /// 49 | /// 拷贝List 50 | /// 51 | /// 源ICollection实现类类型 52 | /// 源ICollection元素类型 53 | /// 源ICollection对象 54 | /// 深拷贝完成的ICollection对象 55 | public static T CopyICollection(T source) 56 | where T : ICollection 57 | { 58 | T result = (T)Utils.CreateNewInstance(source.GetType()); 59 | 60 | if (Utils.IsRefTypeExceptString(typeof(TElement))) 61 | { 62 | foreach (TElement item in source) 63 | { 64 | result.Add(Copier.Copy(item)); 65 | } 66 | } 67 | else 68 | { 69 | foreach (TElement item in source) 70 | { 71 | result.Add(item); 72 | } 73 | } 74 | return result; 75 | } 76 | 77 | /// 78 | /// 拷贝数组 79 | /// 80 | /// 源数组元素类型 81 | /// 源List 82 | /// 深拷贝完成的数组 83 | public static TElement[] CopyArray(TElement[] source) 84 | { 85 | TElement[] result = new TElement[source.Length]; 86 | if (Utils.IsRefTypeExceptString(typeof(TElement))) 87 | { 88 | for (int i = 0; i < source.Length; i++) 89 | { 90 | result[i] = Copier.Copy(source[i]); 91 | } 92 | } 93 | else 94 | { 95 | for (int i = 0; i < source.Length; i++) 96 | { 97 | result[i] = source[i]; 98 | } 99 | } 100 | return result; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/DeepCopier/UnsupportedTypeException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DeepCopier 4 | { 5 | /// 6 | /// 对尚不支持的类型进行拷贝时抛出的异常 7 | /// 8 | public class UnsupportedTypeException : Exception 9 | { 10 | /// 11 | /// 用指定的类型初始化 DeepCopier.UnsupportedTypeException 类的新实例 12 | /// 13 | /// 暂不支持的类型信息 14 | public UnsupportedTypeException(Type type) : base($"Type[{type.Name}] has not been supported yet.") 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/DeepCopier/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Concurrent; 4 | using System.Linq.Expressions; 5 | 6 | namespace DeepCopier 7 | { 8 | /// 9 | /// 工具类 10 | /// 11 | internal static class Utils 12 | { 13 | private static readonly Type _typeString = typeof(string); 14 | 15 | private static readonly Type _typeIEnumerable = typeof(IEnumerable); 16 | 17 | private static readonly ConcurrentDictionary> _ctors = new ConcurrentDictionary>(); 18 | 19 | /// 20 | /// 判断是否是string以外的引用类型 21 | /// 22 | /// True:是string以外的引用类型,False:不是string以外的引用类型 23 | public static bool IsRefTypeExceptString(Type type) 24 | => !type.IsValueType && type != _typeString; 25 | 26 | /// 27 | /// 判断是否是string以外的可遍历类型 28 | /// 29 | /// True:是string以外的可遍历类型,False:不是string以外的可遍历类型 30 | public static bool IsIEnumerableExceptString(Type type) 31 | => _typeIEnumerable.IsAssignableFrom(type) && type != _typeString; 32 | 33 | /// 34 | /// 创建指定类型实例 35 | /// 36 | /// 类型信息 37 | /// 指定类型的实例 38 | public static object CreateNewInstance(Type type) => 39 | _ctors.GetOrAdd(type, 40 | t => Expression.Lambda>(Expression.New(t)).Compile())(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/DeepCopier.Test/DeepCopier.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.0 5 | 6 | false 7 | full 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test/DeepCopier.Test/DeepCopyTest.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eventhorizon-cli/DeepCopier/1cc31d7c4cb15d5dbfc865868db6ca19989c0a04/test/DeepCopier.Test/DeepCopyTest.cs -------------------------------------------------------------------------------- /test/DeepCopier.Test/TestClasses/ClassA.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace DeepCopier.Test.TestClasses 6 | { 7 | class ClassA 8 | { 9 | public int ValueTypeProp { get; set; } 10 | 11 | public string StringProp { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/DeepCopier.Test/TestClasses/ClassB.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace DeepCopier.Test.TestClasses 6 | { 7 | class ClassB 8 | { 9 | public int ValueTypeProp { get; set; } 10 | 11 | public string StringProp { get; set; } 12 | 13 | public ClassA ClassATypeProp { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/DeepCopier.Test/TestClasses/ClassC.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace DeepCopier.Test.TestClasses 6 | { 7 | class ClassC 8 | { 9 | public int ValueTypeProp { get; set; } 10 | 11 | public string StringProp { get; set; } 12 | 13 | public ClassA ClassATypeProp { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/DeepCopier.Test/TestClasses/ClassD.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace DeepCopier.Test.TestClasses 6 | { 7 | class ClassD 8 | { 9 | public int[] VuleTypeArray { get; set; } 10 | 11 | public ClassA[] ClassATypeArray { get; set; } 12 | 13 | public List VuleTypeList { get; set; } 14 | 15 | public List ClassATypeList { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/DeepCopier.Test/TestClasses/ClassE.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace DeepCopier.Test.TestClasses 6 | { 7 | class ClassE 8 | { 9 | public int[] VuleTypeArray { get; set; } 10 | 11 | public ClassA[] ClassATypeArray { get; set; } 12 | 13 | public List VuleTypeList { get; set; } 14 | 15 | public List ClassATypeList { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/DeepCopier.Test/TestClasses/ClassF.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace DeepCopier.Test.TestClasses 6 | { 7 | class ClassF 8 | { 9 | public ICollection ClassACollection { get; set; } 10 | } 11 | } 12 | --------------------------------------------------------------------------------