예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        /// <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);
        }
예제 #5
0
        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);
        }