protected override T CloneComplex <T>(T source, CloningMode mode) { var rank = _type.GetArrayRank(); if (rank > 1) { throw new ArgumentException("Only one-dimensional arrays are supported.", nameof(source)); } var arr = source as Array; switch (mode) { case CloningMode.Deep: var elemType = _type.GetElementType(); var newArray = Array.CreateInstance(elemType, arr.Length); _cloned.Add(source, newArray); for (var i = 0; i < arr.Length; i++) { var value = CloneMakerFactory.GetCloneMaker(arr.GetValue(i), mode, _typeMembers, _cloned).Clone(arr.GetValue(i), mode); newArray.SetValue(value, i); } return((T)(object)newArray); case CloningMode.Shallow: return((T)arr.Clone()); default: throw new ArgumentException("Deep or shallow mode should be defined.", nameof(mode)); } }
public T Clone <T>(T source) { try { return(CloneMakerFactory.GetCloneMaker(source, CloningMode.Deep, _typeMembers, _cloned).Clone(source, CloningMode.Deep)); } catch (ArgumentException ex) { //log it throw; } }
protected override T CloneComplex <T>(T source, CloningMode mode) { var addMethod = _type.GetMethod(AddMethod, BindingFlags.Instance | BindingFlags.Public); var collection = source as IEnumerable; var newCollection = (ICollection)Activator.CreateInstance(_type); _cloned.Add(source, newCollection); foreach (var item in collection) { var value = CloneMakerFactory.GetCloneMaker(item, mode, _typeMembers, _cloned).Clone(item, mode); addMethod.Invoke(newCollection, new object[] { value }); } return((T)newCollection); }
private T CloneWithMembers <T>(T source, IReadOnlyCollection <Tuple <MemberInfo, MemberTypes, CloningMode> > members) { var copy = CreateInstance(source); _cloned.Add(source, copy); foreach (var member in members) { if (member.Item3 == CloningMode.Ignore) { continue; } Func <object> valueGetter; Action <object, object> valueSetter; Func <object> structValueGetter; Action <object, object> structValueSetter; switch (member.Item2) { case MemberTypes.Property: var property = member.Item1 as PropertyInfo; valueGetter = () => CreatePropGetter <T, object>(property)(source); valueSetter = (target, value) => CreatePropSetter <T, object>(property)((T)target, value); structValueGetter = () => property.GetValue(source); structValueSetter = (target, value) => property.SetValue(target, value); break; case MemberTypes.Field: var field = member.Item1 as FieldInfo; valueGetter = () => CreateGetter <T, object>(field)(source); valueSetter = (target, value) => CreateSetter <T, object>(field)((T)target, value); structValueGetter = () => field.GetValue(source); structValueSetter = (target, value) => field.SetValue(target, value); break; default: throw new ArgumentException("Only filed and property cloning supported."); } object sourceValue = null; if (_type.IsValueType) { sourceValue = structValueGetter(); } else { sourceValue = valueGetter(); } if (sourceValue == null) { continue; } var clone = CloneMakerFactory.GetCloneMaker(sourceValue, member.Item3, _typeMembers, _cloned).Clone(sourceValue, member.Item3); if (_type.IsValueType) { object boxed = copy; structValueSetter(boxed, clone); copy = (T)boxed; _cloned[source] = copy; } else { valueSetter(copy, clone); } } return(copy); }