-1

Context

  • Three classes: MetaParticipant, MetaMovie and MetaPerson
  • A MetaParticipant has one MetaMovie and one MetaPerson

To fix an issue, I created a IsEqual static method in all three.

For the independent ones MetaMovie and MetaPerson, I used (MetaPerson has the same except with its class instead):

public static System.Linq.Expressions.Expression<Func<MetaMovie, bool>> IsEqual(MetaMovie other)
{
    if (other.Id > 0) return m => other.Id == m.Id; // Using '> 0' so it skips the new ones in change tracker to the next identifier

    return m => other.MetaSource == m.MetaSource && other.ExternalId == m.ExternalId;
}

So, I would like to write the MetaParticipant.IsEqual method, but ain't able to figure out how.

This method will receive a MetaParticipant that can use its MetaMovie and MetaPerson to call the others.

Issue

Here is the MetaParticipant.Equals that IsEqual shall "replace":

public override bool Equals(object obj)
{
    if (obj == null) return false;
    if (base.Equals(obj)) return true;
    if (obj is not MetaParticipant other) return false;

    return Movie.Equals(other.Movie) && Person.Equals(other.Person) && JobTitle == other.JobTitle;
}

And where I am up to for IsEqual:

public static Expression<Func<MetaParticipant, bool>> IsEqual(MetaParticipant other)
{
    //var own = new Expression<Func<MetaParticipant, bool>() { return x => x.JobTitle == other.JobTitle; };

    var mm = MetaMovie.IsEqual(other.Movie);
    var mp = MetaPerson.IsEqual(other.Person);

    var body = Expression.AndAlso(
        Expression.Invoke(mm, Expression.Parameter(other.Movie.GetType(), "mm")),
        Expression.Invoke(mp, Expression.Parameter(other.Person.GetType(), "mp"))
        );
    //body = Expression.AndAlso(body, );

    var lambda = Expression.Lambda<Func<MetaParticipant, bool>>(body, Expression.Parameter(typeof(MetaParticipant)));
    return lambda;
    //return m => Expression.Invoke(mm, Expression.Variable(m.Movie.GetType())) && m.JobTitle == other.JobTitle;
}

Sorry, there is a bit of garbage I kept so you can see some tries I did.

Master DJon
  • 1,899
  • 2
  • 19
  • 30
  • In your comment on the `return`, where did you get the `m`? I don't see an `m` parameter anywhere (which is a hint as to where you have gone wrong.) And where in your comment is `mp` (`mpIsEqualExpr`)? (Also, reusing mm for a parameter and an expression is a bad idea. Should have used `mmIsEqualExpr` and `mmParm`). – NetMage Feb 22 '23 at 18:43
  • 1
    @NetMage With the hint you gave me, I got it. I will post an answer. – Master DJon Feb 22 '23 at 19:15
  • @NetMage Answer posted. – Master DJon Feb 22 '23 at 19:28
  • @NetMage If you want to take a look at the original question, maybe you would have an idea: https://stackoverflow.com/questions/75394473/ – Master DJon Feb 22 '23 at 19:33

1 Answers1

0

With the help of @NetMage and someone else in another question (but unfortunately he deleted his answer), I figured out how to do it.

With .NET 7.0, I can use the class ReplacingExpressionVisitor to change both expressions to use the accordingly property.

public static Expression<Func<MetaParticipant, bool>> IsEqual(MetaParticipant other)
{
    var participantParam = Expression.Parameter(typeof(MetaParticipant), "m");

    var movieExpression = MetaMovie.IsEqual(other.Movie);
    var movieParamReplacer = new ReplacingExpressionVisitor(new[] { movieExpression.Parameters[0] }, new[] { Expression.Property(participantParam, nameof(Movie)) });

    var personExpression = MetaPerson.IsEqual(other.Person);
    var personParamReplacer = new ReplacingExpressionVisitor(new[] { personExpression.Parameters[0] }, new[] { Expression.Property(participantParam, nameof(Person)) });

    var jobTitleProperty = Expression.Property(participantParam, nameof(JobTitle));
    var otherJobTitle = Expression.Constant(other.JobTitle);
    var jobTitle = Expression.Equal(jobTitleProperty, otherJobTitle);

    var newBody = Expression.AndAlso(movieParamReplacer.Visit(movieExpression.Body), personParamReplacer.Visit(personExpression.Body));
    newBody = Expression.AndAlso(newBody, jobTitle);

    var lambda = Expression.Lambda<Func<MetaParticipant, bool>>(newBody, participantParam);
    return lambda;
}
Master DJon
  • 1,899
  • 2
  • 19
  • 30