public MappingAccordances <TSource, TDestination> Register <TSourceValue, TDestinationValue>( [NotNull] Expression <Func <TSource, TSourceValue> > sourcePropertySelectorExpression, [NotNull] Expression <Func <TDestination, TDestinationValue> > destinationPropertySelectorExpression, [NotNull] MappingAccordances <TSourceValue, TDestinationValue> innerMappingAccordances) { Assert.That(sourcePropertySelectorExpression, Is.Not.Null); Assert.That(destinationPropertySelectorExpression, Is.Not.Null); Assert.That(innerMappingAccordances, Is.Not.Null); var sourcePropertySelector = sourcePropertySelectorExpression.Compile(); var destinationPropertySelector = destinationPropertySelectorExpression.Compile(); var sourceExpression = MappingAccordances.ToReadableString(sourcePropertySelectorExpression); var destinationExpression = MappingAccordances.ToReadableString(destinationPropertySelectorExpression); _assertions.Add( (source, destination, parentFailureMessage) => { var sourcePropertyValue = sourcePropertySelector(source); var destinationPropertyValue = destinationPropertySelector(destination); var failureMessage = MappingAccordances.CreateDetailedFailureMessage( @"The values are expected to match", sourceExpression, destinationExpression, parentFailureMessage); innerMappingAccordances.AssertAllInternal( sourcePropertyValue, destinationPropertyValue, failureMessage); }); return(this); }
public MappingAccordances <TSource, TDestination> Register <TSourceValue, TDestinationValue>( [NotNull] Expression <Func <TSource, TSourceValue> > sourcePropertySelectorExpression, [NotNull] Expression <Func <TDestination, TDestinationValue> > destinationPropertySelectorExpression, [NotNull] ConstraintCreator <TSourceValue> createConstraintFromSourcePropertyValue, [NotNull] MappingAccordances.AssertionFailedMessageCreator <TSourceValue, TDestinationValue> getAssertionFailureMessage) { Assert.That(sourcePropertySelectorExpression, Is.Not.Null); Assert.That(destinationPropertySelectorExpression, Is.Not.Null); Assert.That(createConstraintFromSourcePropertyValue, Is.Not.Null); Assert.That(getAssertionFailureMessage, Is.Not.Null); var sourcePropertySelector = sourcePropertySelectorExpression.Compile(); var destinationPropertySelector = destinationPropertySelectorExpression.Compile(); var sourceExpression = MappingAccordances.ToReadableString(sourcePropertySelectorExpression); var destinationExpression = MappingAccordances.ToReadableString(destinationPropertySelectorExpression); _assertions.Add( (source, destination, parentFailureMessage) => { var sourcePropertyValue = sourcePropertySelector(source); var destinationPropertyValue = destinationPropertySelector(destination); var constraint = createConstraintFromSourcePropertyValue(sourcePropertyValue); Assert.That( constraint, Is.Not.Null, $@"A factory method specified in the argument '{ nameof(createConstraintFromSourcePropertyValue)}' returned an invalid value."); var baseFailureMessage = getAssertionFailureMessage(sourcePropertyValue, destinationPropertyValue); Assert.That( baseFailureMessage, Is.Not.Null.And.Not.Empty, $@"A factory method specified in the argument '{ nameof(getAssertionFailureMessage)}' returned an invalid value."); var failureMessage = MappingAccordances.CreateDetailedFailureMessage( baseFailureMessage, sourceExpression, destinationExpression, parentFailureMessage); Assert.That(destinationPropertyValue, constraint, failureMessage); }); return(this); }
/// <summary> /// Registers all the properties, in source and destination types, that match by name and /// property type. /// </summary> /// <param name="ignoreCase"> /// <c>true</c> if the property name comparison is case insensitive; <c>false</c> if the /// property name comparison is case sensitive. /// </param> /// <returns> /// This <see cref="MappingAccordances{TSource,TDestination}"/> instance. /// </returns> public MappingAccordances <TSource, TDestination> RegisterAllMatchingProperties(bool ignoreCase) { var sourceType = typeof(TSource); var destinationType = typeof(TDestination); var sourceProperties = MappingAccordances.GetSimpleReadableProperties(sourceType, ignoreCase); var destinationProperties = MappingAccordances.GetSimpleReadableProperties(destinationType, ignoreCase); var propertyNameComparer = MappingAccordances.GetPropertyNameComparer(ignoreCase); var matchingNames = sourceProperties .Keys .Intersect(destinationProperties.Keys, propertyNameComparer) .ToArray(); foreach (var name in matchingNames) { var sourceProperty = sourceProperties[name]; var destinationProperty = destinationProperties[name]; var propertyType = sourceProperty.PropertyType; if (propertyType != destinationProperty.PropertyType) { continue; } var sourcePropertySelectorExpression = MappingAccordances.CreatePropertyExpression( sourceType, sourceProperty, "source"); var destinationPropertySelectorExpression = MappingAccordances.CreatePropertyExpression( destinationType, destinationProperty, "destination"); var register = _registerMatchingPropertyMethodInfo.Value.MakeGenericMethod(propertyType); register.Invoke( this, new object[] { sourcePropertySelectorExpression, destinationPropertySelectorExpression }); } return(this); }
/// <summary> /// Registers the check for null reference: /// <list type="bullet"> /// <item> /// <description> /// If source is <c>null</c>, then destination must also be <c>null</c>. /// </description> /// </item> /// <item> /// <description> /// If source is NOT <c>null</c>, then destination must also be NOT <c>null</c>. /// </description> /// </item> /// </list> /// </summary> /// <returns> /// This <see cref="MappingAccordances{TSource,TDestination}"/> instance. /// </returns> /// <remarks> /// In case when the null reference check is registered, if both source and destinaton /// passed to <see cref="AssertAll(TSource,TDestination)"/> are <c>null</c>, then /// assertions for all the registered mappings are skipped and the /// <see cref="AssertAll(TSource,TDestination)"/> call is deemed successful. /// </remarks> public MappingAccordances <TSource, TDestination> RegisterNullReferenceCheck() { if (_nullReferenceAssertion == null) { _nullReferenceAssertion = (source, destination) => { var isSourceNull = MappingAccordances.IsNullReference(source); var isDestinationNull = MappingAccordances.IsNullReference(destination); Assert.That( isDestinationNull, Is.EqualTo(isSourceNull), MappingAccordances.NullMismatchMessage); return(isSourceNull && isDestinationNull); }; } return(this); }
public MappingAccordances <TSource, TDestination> Register <TSourceItem, TDestinationItem>( [NotNull] Expression <Func <TSource, IList <TSourceItem> > > sourcePropertySelectorExpression, [NotNull] Expression <Func <TDestination, IList <TDestinationItem> > > destinationPropertySelectorExpression, [NotNull] MappingAccordances <TSourceItem, TDestinationItem> innerMappingAccordances) { Assert.That(sourcePropertySelectorExpression, Is.Not.Null); Assert.That(destinationPropertySelectorExpression, Is.Not.Null); Assert.That(innerMappingAccordances, Is.Not.Null); var sourcePropertySelector = sourcePropertySelectorExpression.Compile(); var destinationPropertySelector = destinationPropertySelectorExpression.Compile(); var sourceExpression = MappingAccordances.ToReadableString(sourcePropertySelectorExpression); var destinationExpression = MappingAccordances.ToReadableString(destinationPropertySelectorExpression); _assertions.Add( (source, destination, parentFailureMessage) => { var sourcePropertyValue = sourcePropertySelector(source); var destinationPropertyValue = destinationPropertySelector(destination); var isSourcePropertyValueNull = MappingAccordances.IsNullReference(sourcePropertyValue); var isDestinationPropertyValueNull = MappingAccordances.IsNullReference(destinationPropertyValue); var nullMismatchMessage = MappingAccordances.CreateDetailedFailureMessage( MappingAccordances.ListValueNullMismatchMessage, sourceExpression, destinationExpression, parentFailureMessage); Assert.That( isDestinationPropertyValueNull, Is.EqualTo(isSourcePropertyValueNull), nullMismatchMessage); if (isSourcePropertyValueNull && isDestinationPropertyValueNull) { return; } var itemCount = destinationPropertyValue.Count; var countMismatchMessage = MappingAccordances.CreateDetailedFailureMessage( MappingAccordances.ListValueCountMismatchMessage, sourceExpression, destinationExpression, parentFailureMessage); Assert.That(itemCount, Is.EqualTo(sourcePropertyValue.Count), countMismatchMessage); for (var index = 0; index < itemCount; index++) { var sourceItem = sourcePropertyValue[index]; var destinationItem = destinationPropertyValue[index]; var itemMismatchMessage = MappingAccordances.CreateDetailedFailureMessage( $@"The source and destination must have the matching item at index {index}", sourceExpression, destinationExpression, parentFailureMessage); innerMappingAccordances.AssertAllInternal(sourceItem, destinationItem, itemMismatchMessage); } }); return(this); }