MetaParticipant
, MetaMovie
and MetaPerson
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.
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.
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;
}