Skip to content

Commit

Permalink
Merge pull request #7
Browse files Browse the repository at this point in the history
Default equalization rules use dynamic computation instead of reflection
  • Loading branch information
TonyTroeff authored Dec 12, 2021
2 parents 4ccec82 + a6f7e17 commit 100dde1
Show file tree
Hide file tree
Showing 10 changed files with 52 additions and 157 deletions.
8 changes: 5 additions & 3 deletions TryAtSoftware.Equalizer.Core/EqualizationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@

public class EqualizationOptions : IEqualizationOptions
{
public EqualizationOptions([NotNull] Type principalType, [NotNull] Type subordinateType, [NotNull] Func<object, object, IEqualizationResult> assertEquality)
private readonly Func<object, object, IEqualizationResult> _equalize;

public EqualizationOptions([NotNull] Type principalType, [NotNull] Type subordinateType, [NotNull] Func<object, object, IEqualizationResult> equalize)
{
this.PrincipalType = principalType ?? throw new ArgumentNullException(nameof(principalType));
this.SubordinateType = subordinateType ?? throw new ArgumentNullException(nameof(subordinateType));
this.AssertEquality = assertEquality ?? throw new ArgumentNullException(nameof(assertEquality));
this._equalize = equalize ?? throw new ArgumentNullException(nameof(equalize));
}

public Type PrincipalType { get; }
public Type SubordinateType { get; }
public Func<object, object, IEqualizationResult> AssertEquality { get; }
public IEqualizationResult Equalize(object expected, object actual) => this._equalize(expected, actual);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ public interface IEqualizationOptions
Type SubordinateType { get; }

[NotNull]
Func<object, object, IEqualizationResult> AssertEquality { get; }
IEqualizationResult Equalize(object expected, object actual);
}
24 changes: 0 additions & 24 deletions TryAtSoftware.Equalizer.Core/MembersBinderCache.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public override IEqualizationResult Equalize(IEnumerable<object> expected, IEnum
var expectedElement = iteratedExpected[i];
var actualElement = iteratedActual[i];

var equalizationResult = options.AssertEquality(expectedElement, actualElement);
var equalizationResult = options.Equalize(expectedElement, actualElement);
if (equalizationResult.IsSuccessful) continue;

var errorMessage = this.UnsuccessfulEqualization(expectedElement, actualElement, $"Element at index {i} do not match");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,48 @@

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using TryAtSoftware.Equalizer.Core.Extensions;
using TryAtSoftware.Equalizer.Core.Interfaces;
using TryAtSoftware.Equalizer.Core.Profiles.Complex.Rules;
using TryAtSoftware.Extensions.Reflection;

public class ComplexEqualizationProfile<T1, T2> : BaseTypedEqualizationProfile<T1, T2>
public class ComplexEqualizationProfile<TPrincipal, TSubordinate> : BaseTypedEqualizationProfile<TPrincipal, TSubordinate>
{
private readonly List<IEqualizationRule<T1, T2>> _rules = new();
private readonly List<IEqualizationRule<TPrincipal, TSubordinate>> _rules = new();

public override IEqualizationResult Equalize(T1 expected, T2 actual, IEqualizationOptions options)
public override IEqualizationResult Equalize(TPrincipal expected, TSubordinate actual, IEqualizationOptions options)
{
if (expected is null && actual is null) return new SuccessfulEqualizationResult();
if (expected is null || actual is null) return new UnsuccessfulEqualizationResult(this.UnsuccessfulEqualization(expected, actual));

foreach (var rule in this._rules)
{
var equalizationResult = rule.Equalize(expected, actual, options);
if (!equalizationResult.IsSuccessful)
return equalizationResult;
if (equalizationResult.IsSuccessful) continue;

var errorMessage = this.UnsuccessfulEqualization(expected, actual);
return new UnsuccessfulEqualizationResult(errorMessage.With(equalizationResult));
}

return new SuccessfulEqualizationResult();
}

protected void Equalize(Expression<Func<T1, object>> expectedValueExpressionSelector, Expression<Func<T2, object>> actualValueExpressionSelector)
protected void Equalize(Func<TPrincipal, object> expectedValueSelector, Func<TSubordinate, object> actualValueSelector)
{
var expectedValueMemberInfo = expectedValueExpressionSelector.GetMemberInfo();
var actualValueMemberInfo = actualValueExpressionSelector.GetMemberInfo();
var rule = new EqualizationRule<T1, T2>(expectedValueMemberInfo.Name, actualValueMemberInfo.Name);
var rule = new EqualizationRule<TPrincipal, TSubordinate>(expectedValueSelector, actualValueSelector);
this.AddRule(rule);
}

protected void Equalize<TValue>(TValue value, Expression<Func<T2, object>> actualValueExpressionSelector)
{
var actualValueMemberInfo = actualValueExpressionSelector.GetMemberInfo();
var rule = new ConstantValueEqualizationRule<T1, T2>(value, actualValueMemberInfo.Name);
this.AddRule(rule);
}
protected void Equalize<TValue>(TValue value, Func<TSubordinate, object> actualValueSelector) => this.Equalize(_ => value, actualValueSelector);

protected void Differentiate(Expression<Func<T1, object>> expectedValueExpressionSelector, Expression<Func<T2, object>> actualValueExpressionSelector)
protected void Differentiate(Func<TPrincipal, object> expectedValueSelector, Func<TSubordinate, object> actualValueSelector)
{
var expectedValueMemberInfo = expectedValueExpressionSelector.GetMemberInfo();
var actualValueMemberInfo = actualValueExpressionSelector.GetMemberInfo();
var rule = new DifferentiationRule<T1, T2>(expectedValueMemberInfo.Name, actualValueMemberInfo.Name);
var rule = new DifferentiationRule<TPrincipal, TSubordinate>(expectedValueSelector, actualValueSelector);
this.AddRule(rule);
}

protected void Differentiate<TValue>(TValue value, Expression<Func<T2, object>> actualValueExpressionSelector)
{
var actualValueMemberInfo = actualValueExpressionSelector.GetMemberInfo();
var rule = new ConstantValueDifferentiationRule<T1, T2>(value, actualValueMemberInfo.Name);
this.AddRule(rule);
}
protected void Differentiate<TValue>(TValue value, Func<TSubordinate, object> actualValueSelector) => this.Differentiate(_ => value, actualValueSelector);

protected bool AddRule(IEqualizationRule<T1, T2> equalizationRule)
protected bool AddRule(IEqualizationRule<TPrincipal, TSubordinate> equalizationRule)
{
if (equalizationRule is null)
return false;
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,30 @@

using System;
using JetBrains.Annotations;
using TryAtSoftware.Equalizer.Core.Extensions;
using TryAtSoftware.Equalizer.Core.Interfaces;
using TryAtSoftware.Extensions.Reflection;

public class DifferentiationRule<T1, T2> : IEqualizationRule<T1, T2>
public class DifferentiationRule<TPrincipal, TSubordinate> : IEqualizationRule<TPrincipal, TSubordinate>
{
private readonly string _expectedValueMemberName;
private readonly string _actualValueMemberName;
[NotNull]
private readonly Func<TPrincipal, object> _expectedValueRetrieval;

public DifferentiationRule([NotNull] string expectedValueMemberName, [NotNull] string actualValueMemberName)
{
if (string.IsNullOrWhiteSpace(expectedValueMemberName))
throw new ArgumentNullException(nameof(expectedValueMemberName));
if (string.IsNullOrWhiteSpace(actualValueMemberName))
throw new ArgumentNullException(nameof(actualValueMemberName));
[NotNull]
private readonly Func<TSubordinate, object> _actualValueRetrieval;

this._expectedValueMemberName = expectedValueMemberName;
this._actualValueMemberName = actualValueMemberName;
public DifferentiationRule([NotNull] Func<TPrincipal, object> expectedValueRetrieval, [NotNull] Func<TSubordinate, object> actualValueRetrieval)
{
this._expectedValueRetrieval = expectedValueRetrieval ?? throw new ArgumentNullException(nameof(expectedValueRetrieval));
this._actualValueRetrieval = actualValueRetrieval ?? throw new ArgumentNullException(nameof(actualValueRetrieval));
}

public IEqualizationResult Equalize(T1 expected, T2 actual, IEqualizationOptions options)
public IEqualizationResult Equalize(TPrincipal expected, TSubordinate actual, IEqualizationOptions options)
{
var expectedValueMemberInfo = MembersBinderCache<T1>.Binder.GetRequiredMemberInfo(this._expectedValueMemberName);
var expectedValue = expectedValueMemberInfo.GetValue(expected);
var constantDifferentiationRule = new ConstantValueDifferentiationRule<T1, T2>(expectedValue, this._actualValueMemberName);
var expectedValue = this._expectedValueRetrieval(expected);
var actualValue = this._actualValueRetrieval(actual);

return constantDifferentiationRule.Equalize(expected, actual, options);
var equalizationResult = options.Equalize(expectedValue, actualValue);
if (!equalizationResult.IsSuccessful) return new SuccessfulEqualizationResult();
return new UnsuccessfulEqualizationResult(this.UnsuccessfulDifferentiation(expectedValue, actualValue));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,28 @@

using System;
using JetBrains.Annotations;
using TryAtSoftware.Extensions.Reflection;
using TryAtSoftware.Equalizer.Core.Extensions;
using TryAtSoftware.Equalizer.Core.Interfaces;

public class EqualizationRule<T1, T2> : IEqualizationRule<T1, T2>
public class EqualizationRule<TPrincipal, TSubordinate> : IEqualizationRule<TPrincipal, TSubordinate>
{
private readonly string _expectedValueMemberName;
private readonly string _actualValueMemberName;
[NotNull]
private readonly Func<TPrincipal, object> _expectedValueRetrieval;

public EqualizationRule([NotNull] string expectedValueMemberName, [NotNull] string actualValueMemberName)
{
if (string.IsNullOrWhiteSpace(expectedValueMemberName))
throw new ArgumentNullException(nameof(expectedValueMemberName));
if (string.IsNullOrWhiteSpace(actualValueMemberName))
throw new ArgumentNullException(nameof(actualValueMemberName));
[NotNull]
private readonly Func<TSubordinate, object> _actualValueRetrieval;

this._expectedValueMemberName = expectedValueMemberName;
this._actualValueMemberName = actualValueMemberName;
public EqualizationRule([NotNull] Func<TPrincipal, object> expectedValueRetrieval, [NotNull] Func<TSubordinate, object> actualValueRetrieval)
{
this._expectedValueRetrieval = expectedValueRetrieval ?? throw new ArgumentNullException(nameof(expectedValueRetrieval));
this._actualValueRetrieval = actualValueRetrieval ?? throw new ArgumentNullException(nameof(actualValueRetrieval));
}

public IEqualizationResult Equalize(T1 expected, T2 actual, IEqualizationOptions options)
public IEqualizationResult Equalize(TPrincipal expected, TSubordinate actual, IEqualizationOptions options)
{
var expectedValueMemberInfo = MembersBinderCache<T1>.Binder.GetRequiredMemberInfo(this._expectedValueMemberName);

var expectedValue = expectedValueMemberInfo.GetValue(expected);
var constantEqualizationRule = new ConstantValueEqualizationRule<T1, T2>(expectedValue, this._actualValueMemberName);
var expectedValue = this._expectedValueRetrieval(expected);
var actualValue = this._actualValueRetrieval(actual);

return constantEqualizationRule.Equalize(expected, actual, options);
return options.Equalize(expectedValue, actualValue);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<LangVersion>latest</LangVersion>

<PackageId>TryAtSoftware.Equalizer</PackageId>
<Version>1.0.0-alpha.3</Version>
<Version>1.0.0-alpha.4</Version>
<Authors>Tony Troeff</Authors>
<RepositoryUrl>https://github.com/TryAtSoftware/Equalizer</RepositoryUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
Expand All @@ -18,7 +18,6 @@
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2021.3.0" PrivateAssets="all" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="8.33.0.40503" PrivateAssets="all" />
<PackageReference Include="TryAtSoftware.Extensions.Reflection" Version="1.0.0-alpha.4" />
</ItemGroup>

</Project>

0 comments on commit 100dde1

Please sign in to comment.