Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider accepting a Visitor in SemanticComparer<T> #219

Closed
moodmosaic opened this issue Dec 7, 2013 · 3 comments
Closed

Consider accepting a Visitor in SemanticComparer<T> #219

moodmosaic opened this issue Dec 7, 2013 · 3 comments
Assignees

Comments

@moodmosaic
Copy link
Member

The SemanticComparer<T> could accept an IReflectionVisitor in order to have a more flexible and polymorphic API.

This would also address #141 (and if all goes well, the IMemberComparer interface could be eventually deprecated.)

This currently acts as a placeholder since I haven't thoroughly considered all the scenarios yet.

@moodmosaic
Copy link
Member Author

Inspired by the samples in Albedo's README about Collecting values and Comparison I am thinking that:

  • SemanticComparer's IMemberComparer could be replaced by Albedo's IReflectionVisitor hierarchies.
  • IReflectionVisitor hierarchies could create a default implementation for SemanticComparer.

We could address that way #141 as well as #48 and then we could possibly define a fluent interface acting as a DSL.

Such a DSL could describe Visitors as shown in the test1 below:

[Fact]
public void Foo()
{
    var value = new Bar(
        1, "abc", 3, Guid.Empty);

    var other = new Bar(
        1, "ABC", 3, Guid.NewGuid());

    var sut =
        new SemanticComparer<Bar>(
            new ValueCollectingVisitor<Bar>(value)
                .With(x => x.Property2, "ABC")
                .Without(x => x.Property4),
            new ValueCollectingVisitor<Bar>(other)
                .Without(x => x.Property4));

    var actual = sut.Equals(value, other);

    Assert.True(actual);
}

Once we get a decent object model and build a DSL on top of SemanticComparer<T> we could deprecate:

Likeness<TSource, TDestination>
SemanticComparer<TSource, TDestination>
IMemberComparer (if replaced by Albedo's IReflectionVisitor)

Any comments or suggestions are always welcome.



1 The implementation of `SemanticComparer` Equals method for passing the above test looks like:
var flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
return
    !new CompositeReflectionElement(x
        .GetType()
        .GetProperties(flags)
        .Select(pi => new PropertyInfoElement(pi))
        .Cast<IReflectionElement>()
        .Concat(x
            .GetType()
            .GetFields(flags)
            .Select(fi => new FieldInfoElement(fi))
            .Cast<IReflectionElement>())
        .ToArray())
        .Accept(this.valueCollectingVisitorX)
        .Value
        .Cast<object>()
        .Except(new CompositeReflectionElement(y
            .GetType()
            .GetProperties(flags)
            .Select(pi => new PropertyInfoElement(pi))
            .Cast<IReflectionElement>()
            .Concat(y
                .GetType()
                .GetFields(flags)
                .Select(fi => new FieldInfoElement(fi))
                .Cast<IReflectionElement>())
            .ToArray())
            .Accept(this.valueCollectingVisitorY)
            .Value
            .Cast<object>())
        .Any();

@moodmosaic
Copy link
Member Author

After re-reading and thinking about the DSL... I am actually unhappy with it as it makes the processing steps implicit.

If we invoke the Zen of Python where "explicit is better than implicit" it's obvious that the processing steps could be modeled with a pipeline to separate the processing into small, concrete, tasks.

We might need to introduce the notion of a Pipe in a similar way as @ploeh did in the Advanced Unit Testing course.

@moodmosaic
Copy link
Member Author

Closing this issue for now due to lack of progress.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant