-
Notifications
You must be signed in to change notification settings - Fork 167
Avoid calling setter for bound properties for same value #3129
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
Conversation
Two things:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that I think about it, I wonder if there's a Sync-related reason why we might not want to avoid the redundant set in all cases. @nirinchev, do you know if it matters for the sync history that a set is recorded here anyway?
{ | ||
return managingRealm.Write(() => | ||
if (_getterMi.Invoke(realmObject, null).Equals(parameters[0])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not crazy about the reflection here. I would've preferred punching straight to the accessor's GetValue. But this is by definition not a hot path, so I suppose it doesn't really matter. But a comment explaining why we do this is necessary, ideally linking to the issue for the full context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll definitely add a comment.
I was thinking about using GetValue
here, but it starts to get a little more complex because we also don't know exactly what is the mapTo
name of the property
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the property value is null
this will throw, wouldn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems reasonable. I have a few minor comments/suggestions.
{ | ||
return managingRealm.Write(() => | ||
if (_getterMi.Invoke(realmObject, null).Equals(parameters[0])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the property value is null
this will throw, wouldn't it?
return null; | ||
} | ||
|
||
var managingRealm = (obj as IRealmObjectBase)?.Realm; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have realmObject
- there's no need to do an extra cast here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Defnitely
|
||
public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) | ||
{ | ||
var managingRealm = (obj as IRealmObjectBase)?.Realm; | ||
var realmObject = obj as IRealmObjectBase; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add an early return here in case obj is not IRealmObjectBase
and remove all the null propagation operators?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only have one one null propagation line (realmObject?.IsManaged == true
), so I suppose we can keep just that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can still make the checks cleaner by merging the cast with the if
-clause (I'm kind of surprised VS isn't hinting this):
if (obj is IRealmObjectBase realmObject && realmObject.IsManaged)
{
// ...
}
Yes, it matters for conflict resolution, but I believe this solution is still the right one considering MAUI's bug. Re-setting all properties every time the UI renders is most likely not what the user intends to do anyway, so this one is the lesser of two evils. |
var managingRealm = realmObject.Realm; | ||
|
||
// If managingRealm is not null and not currently in transaction, wrap setting the property in a realm.Write(...) | ||
if (realmObject.Realm?.IsInTransaction == false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use managingRealm
here.
|
||
public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) | ||
{ | ||
var managingRealm = (obj as IRealmObjectBase)?.Realm; | ||
var realmObject = obj as IRealmObjectBase; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can still make the checks cleaner by merging the cast with the if
-clause (I'm kind of surprised VS isn't hinting this):
if (obj is IRealmObjectBase realmObject && realmObject.IsManaged)
{
// ...
}
Avoids calling the setter for bound properties in case the new value is the same as the old one. This avoids a problem in MAUI in which the UI is calling the setter unnecessarily, and causing an issue in case objects outside of the user's write permissions are modified
Fixes #3128
TODO