/// <summary> /// Determines whether two lists of <see cref="MemberBinding"/> are similar. /// </summary> /// <param name="source">The source list.</param> /// <param name="target">The target list.</param> /// <returns>A value indicating whether the individual bindings are similar.</returns> public static bool MemberBindingsAreSimilar( IList <MemberBinding> source, IList <MemberBinding> target) { if (source.Count() != target.Count()) { return(false); } var similar = true; for (var idx = 0; idx < source.Count() && similar; idx += 1) { if (source[idx].BindingType != target[idx].BindingType) { return(false); } if (source[idx] is MemberAssignment assign) { var targetAssign = target[idx] as MemberAssignment; similar = assign.Member.MemberType == targetAssign.Member.MemberType && TypesAreSimilar(assign.Member.DeclaringType, targetAssign.Member.DeclaringType) && IsPartOf(assign.Expression, targetAssign.Expression); } if (source[idx] is MemberMemberBinding memberMemberBinding) { var targetMemberBinding = target[idx] as MemberMemberBinding; similar = memberMemberBinding.Member.MemberType == targetMemberBinding.Member.MemberType && TypesAreSimilar(memberMemberBinding.Member.DeclaringType, targetMemberBinding.Member.DeclaringType) && MemberBindingsAreSimilar(memberMemberBinding.Bindings, targetMemberBinding.Bindings); } if (source[idx] is MemberListBinding memberListBinding) { var targetListBinding = target[idx] as MemberListBinding; similar = memberListBinding.Member.MemberType == targetListBinding.Member.MemberType && TypesAreSimilar(memberListBinding.Member.DeclaringType, targetListBinding.Member.DeclaringType) && ExpressionEquivalency.NonGenericEnumerablesAreEquivalent( memberListBinding.Initializers, targetListBinding.Initializers); } } return(similar); }
/// <summary> /// Ensures that two <see cref="MemberBinding"/> instances are equivalent. /// </summary> /// <param name="source">The source <see cref="MemberBinding"/>.</param> /// <param name="target">The target <see cref="MemberBinding"/>.</param> /// <returns>A value that indicates whether the bindings are equivalent.</returns> public bool MemberBindingsAreEquivalent(MemberBinding source, MemberBinding target) => ExpressionEquivalency.MemberBindingsAreEquivalent(source, target);
/// <summary> /// Ensures two dictionaries are equivalent. /// </summary> /// <param name="source">The source <see cref="IDictionary"/>.</param> /// <param name="target">The target <see cref="IDictionary"/>.</param> /// <returns>A value indicating whether the dictionaries are equivalent.</returns> public bool DictionariesAreEquivalent(IDictionary source, IDictionary target) => ExpressionEquivalency.DictionariesAreEquivalent(source, target);
/// <summary> /// Determine if a <see cref="Type"/> is equivalent to another type. /// </summary> /// <remarks> /// Handles anonymous types converted to dynamic dictionary. /// </remarks> /// <param name="source">The source <see cref="Type"/>.</param> /// <param name="target">The target <see cref="Type"/>.</param> /// <returns>A value indicating whether the types are equivalent.</returns> public bool TypesAreEquivalent(Type source, Type target) => ExpressionEquivalency.TypesAreEquivalent(source, target);
/// <summary> /// Attempts to compare values in various ways. /// </summary> /// <remarks> /// <para>If one side is <c>null</c> and other is not <c>null</c>, returns <c>false</c>. If the objects are the same reference, /// returns <c>true</c>. If the type implements <see cref="IEquatable{T}"/> then the result of <see cref="IEquatable{T}.Equals(T)"/> /// is returned. If the type implements <see cref="IComparable"/> then the result is <c>true</c> if /// <see cref="IComparable.CompareTo(object)"/> is <c>0</c>. Otherwise, the result of <see cref="object.Equals(object)"/> from /// the source to the target is returned.</para> /// <para>Exceptions are compared by the `Message` property. The comparison is also recursive: if a type is found that has an /// existing comparison method, the method is called for further validation.</para> /// </remarks> /// <param name="source">The source value.</param> /// <param name="target">The target value.</param> /// <returns>A flag indicating equivalency.</returns> public bool ValuesAreEquivalent(object source, object target) => ExpressionEquivalency.ValuesAreEquivalent(source, target);
/// <summary> /// Comparison of multiple expressions. Equivalent /// only when all elements match, in order, and /// pass the equivalent test. /// </summary> /// <param name="source">The source expressions.</param> /// <param name="target">The target expressions.</param> /// <returns>A flag indicating whether the two sets of /// expressions are equivalent.</returns> public bool AreEquivalent( IEnumerable <Expression> source, IEnumerable <Expression> target) => ExpressionEquivalency.AreEquivalent(source, target);
/// <summary> /// Entry for equivalency comparisons. Will cast to /// known types and compare. /// </summary> /// <typeparam name="T">The <see cref="Type"/> of the entity.</typeparam> /// <param name="source">The source <see cref="IQueryable{T}"/>.</param> /// <param name="target">The target <see cref="IQueryable{T}"/> to compare to.</param> /// <returns>A flag indicating whether the source and target are equivalent.</returns> public bool AreEquivalent <T>(IQueryable <T> source, IQueryable <T> target) => ExpressionEquivalency.AreEquivalent(source?.Expression, target?.Expression);
/// <summary> /// Entry for equivalency comparisons. Will cast to /// known types and compare. /// </summary> /// <param name="source">The source <see cref="Expression"/>.</param> /// <param name="target">The target <see cref="Expression"/> to compare to.</param> /// <returns>A flag indicating whether the source and target are equivalent.</returns> public bool AreEquivalent(Expression source, Expression target) => ExpressionEquivalency.AreEquivalent(source, target);
/// <summary> /// Comparison matrix for types and nulls. /// </summary> /// <param name="source">The source to compare.</param> /// <param name="other">The target to compare to.</param> /// <returns>A flag indicating whether the types are /// equal and the values are both not null.</returns> public bool NullAndTypeCheck(Expression source, Expression other) => ExpressionEquivalency.NullAndTypeCheck(source, other);
/// <summary> /// Ensures two enumerables are same length an each value is equivalent. /// </summary> /// <param name="srcEnumerable">The source <see cref="IEnumerable"/>.</param> /// <param name="tgtEnumerable">The target <see cref="IEnumerable"/>.</param> /// <returns>A flag indicating whether the two are equivalent.</returns> public bool NonGenericEnumerablesAreEquivalent(IEnumerable srcEnumerable, IEnumerable tgtEnumerable) => ExpressionEquivalency.NonGenericEnumerablesAreEquivalent(srcEnumerable, tgtEnumerable);