private static void CollectionItems( object source, object target, MemberSettings settings, ReferencePairCollection referencePairs) { if (!Is.Enumerable(source, target)) { return; } if (settings.ReferenceHandling == ReferenceHandling.Throw && !settings.IsImmutable(source.GetType().GetItemType())) { throw State.Throw.ShouldNeverGetHereException("Should have been checked for throw before copy"); } if (ArrayCopyer.TryGetOrCreate(source, target, out var copyer) || ListOfTCopyer.TryGetOrCreate(source, target, out copyer) || ListCopyer.TryGetOrCreate(source, target, out copyer) || DictionaryTKeyTValueCopyer.TryGetOrCreate(source, target, out copyer) || DictionaryCopyer.TryGetOrCreate(source, target, out copyer) || SetOfTCopyer.TryGetOrCreate(source, target, out copyer)) { copyer.Copy(source, target, settings, referencePairs); return; } if (source is IEnumerable || target is IEnumerable) { throw State.Throw.ShouldNeverGetHereException("Should be checked before"); } }
private static ErrorBuilder.TypeErrorsBuilder VerifyCore(MemberSettings settings, Type type) { return(ErrorBuilder.Start() .CheckRequiresReferenceHandling(type, settings, t => !settings.IsImmutable(t)) .CheckIsCopyableEnumerable(type, settings) .CheckIndexers(type, settings)); }
private static TypeErrors CreateErrors(Type type, MemberSettings settings, MemberPath path) { if (settings.IsImmutable(type)) { return(null); } var errors = ErrorBuilder.Start() .CheckRequiresReferenceHandling(type, settings, x => !settings.IsImmutable(x)) .CheckIndexers(type, settings) .CheckNotifies(type, settings) .VerifyRecursive(type, settings, path, GetNodeErrors) .Finnish(); return(errors); }
internal static TypeErrorsBuilder CheckNotifies(this TypeErrorsBuilder typeErrors, Type type, MemberSettings settings) { if (settings.IsImmutable(type)) { return(typeErrors); } if (typeof(IEnumerable).IsAssignableFrom(type)) { if (!typeof(INotifyCollectionChanged).IsAssignableFrom(type)) { return(typeErrors.CreateIfNull(type) .Add(CollectionMustNotifyError.GetOrCreate(type))); } } else if (!typeof(INotifyPropertyChanged).IsAssignableFrom(type)) { if (settings.IsIgnoringDeclaringType(type)) { return(typeErrors); } return(typeErrors.CreateIfNull(type) .Add(TypeMustNotifyError.GetOrCreate(type))); } return(typeErrors); }
internal static object CreateInstance(object sourceValue, MemberSettings settings) { if (sourceValue == null) { return(null); } var type = sourceValue.GetType(); if (type.IsArray) { var constructor = type.GetConstructor(new[] { typeof(int) }); var parameters = new[] { type.GetProperty("Length").GetValue(sourceValue) }; //// ReSharper disable once PossibleNullReferenceException nope, never null here var array = constructor.Invoke(parameters); return(array); } if (settings.IsImmutable(type)) { return(sourceValue); } try { return(Activator.CreateInstance(type, true)); } catch (Exception e) { throw Throw.CreateCannotCreateInstanceException(sourceValue, settings, e); } }
private static void CollectionItems( object source, object target, MemberSettings settings, ReferencePairCollection referencePairs) { if (!Is.Enumerable(source, target)) { return; } if (settings.ReferenceHandling == ReferenceHandling.Throw && !settings.IsImmutable(source.GetType().GetItemType())) { throw State.Throw.ShouldNeverGetHereException("Should have been checked for throw before copy"); } ICopyer copyer; if (ArrayCopyer.TryGetOrCreate(source, target, out copyer) || ListOfTCopyer.TryGetOrCreate(source, target, out copyer) || ListCopyer.TryGetOrCreate(source, target, out copyer) || DictionaryTKeyTValueCopyer.TryGetOrCreate(source, target, out copyer) || DictionaryCopyer.TryGetOrCreate(source, target, out copyer) || SetOfTCopyer.TryGetOrCreate(source, target, out copyer)) { copyer.Copy(source, target, settings, referencePairs); return; } if (source is IEnumerable || target is IEnumerable) { throw State.Throw.ShouldNeverGetHereException("Should be checked before"); } }
private static void Copy <T>( ISet <T> source, ISet <T> target, MemberSettings settings, ReferencePairCollection referencePairs) { if (Is.IsFixedSize(source, target) && source.Count != target.Count) { throw State.Copy.Throw.CannotCopyFixesSizeCollections(source, target, settings); } if (settings.IsImmutable(typeof(T))) { using (var borrow = HashSetPool <T> .Borrow(EqualityComparer <T> .Default)) { borrow.Value.UnionWith(source); target.IntersectWith(borrow.Value); target.UnionWith(borrow.Value); return; } } switch (settings.ReferenceHandling) { case ReferenceHandling.Throw: break; case ReferenceHandling.References: using (var borrow = HashSetPool <T> .Borrow((x, y) => ReferenceEquals(x, y), x => RuntimeHelpers.GetHashCode(x))) { borrow.Value.UnionWith(source); target.IntersectWith(borrow.Value); target.UnionWith(borrow.Value); } break; case ReferenceHandling.Structural: IEqualityComparer <T> comparer; if (!Set.TryGetComparer(source, out comparer)) { comparer = EqualityComparer <T> .Default; } var copyIngComparer = new CopyingComparer <T>(comparer, settings, referencePairs); using (var borrow = HashSetPool <T> .Borrow(copyIngComparer)) { borrow.Value.UnionWith(source); target.IntersectWith(borrow.Value); copyIngComparer.StartCopying(); target.UnionWith(borrow.Value); } return; default: throw new ArgumentOutOfRangeException(); } }
internal static bool IsCopyValue(Type type, MemberSettings settings) { if (settings.IsImmutable(type) || settings.ReferenceHandling == ReferenceHandling.References) { return(true); } return(false); }
private static void Member <T>( T source, T target, MemberSettings settings, ReferencePairCollection referencePairs, IGetterAndSetter getterAndSetter) { var sv = getterAndSetter.GetValue(source); var tv = getterAndSetter.GetValue(target); if (getterAndSetter.IsInitOnly) { if (settings.IsImmutable(getterAndSetter.ValueType) || sv == null) { return; } Sync(sv, tv, settings, referencePairs); return; } if (settings.IsImmutable(getterAndSetter.ValueType) || sv == null) { getterAndSetter.CopyValue(source, target); return; } bool created; bool needsSync; var clone = CloneWithoutSync(sv, tv, settings, out created, out needsSync); if (created) { getterAndSetter.SetValue(target, clone); } if (needsSync) { Sync(sv, clone, settings, referencePairs); } }
internal static void CanCopyRoot(Type type, MemberSettings settings) { if (settings.IsImmutable(type)) { throw new NotSupportedException("Cannot copy the members of an immutable object"); } if (typeof(IEnumerable).IsAssignableFrom(type) && !IsCopyableCollectionType(type)) { throw new NotSupportedException($"Can only copy the members of collections implementing {typeof(IList).Name} or {typeof(IDictionary).Name}"); } }
private static TypeErrors CreateErrors(Type type, MemberSettings settings, MemberPath path) { if (settings.IsImmutable(type) || settings.TryGetCopyer(type, out var temp)) { return(null); } var errors = VerifyCore(settings, type) .VerifyRecursive(type, settings, path, GetNodeErrors) .Finnish(); return(errors); }
private static bool TryCopyValue <T>(T x, T y, MemberSettings settings, out T result) { if (ReferenceEquals(x, y)) { result = x; return(true); } if (x == null) { // ReSharper disable once ExpressionIsAlwaysNull R# not getting static analysis right here result = x; return(true); } if (settings.IsImmutable(x.GetType())) { result = x; return(true); } result = default(T); return(false); }
internal static TypeErrorsBuilder CheckNotifies(this TypeErrorsBuilder typeErrors, Type type, MemberSettings settings) { if (settings.IsImmutable(type)) { return typeErrors; } if (type.IsValueType) { if (typeof(INotifyCollectionChanged).IsAssignableFrom(type) || typeof(INotifyPropertyChanged).IsAssignableFrom(type)) { return typeErrors.CreateIfNull(type) .Add(StructMustNotNotifyError.GetOrCreate(type)); } return typeErrors; } if (typeof(IEnumerable).IsAssignableFrom(type)) { if (!typeof(INotifyCollectionChanged).IsAssignableFrom(type)) { return typeErrors.CreateIfNull(type) .Add(CollectionMustNotifyError.GetOrCreate(type)); } } else if (!typeof(INotifyPropertyChanged).IsAssignableFrom(type)) { if (settings.IsIgnoringDeclaringType(type)) { return typeErrors; } return typeErrors.CreateIfNull(type) .Add(TypeMustNotifyError.GetOrCreate(type)); } return typeErrors; }