@@ -47,6 +47,7 @@ public interface IMonkeySyncObject : INotifyPropertyChanged, IDisposable
4747 /// <summary>
4848 /// Gets whether this sync object has a valid link.
4949 /// </summary>
50+ [ MemberNotNullWhen ( true , nameof ( LinkObject ) ) ]
5051 public bool IsLinkValid { get ; }
5152
5253 /// <summary>
@@ -106,6 +107,7 @@ public abstract class MonkeySyncObject<TSyncObject, TSyncValue, TLink> : IUnlink
106107 public bool HasLinkObject => LinkObject is not null ;
107108
108109 /// <inheritdoc/>
110+ [ MemberNotNullWhen ( true , nameof ( LinkObject ) ) ]
109111 public abstract bool IsLinkValid { get ; }
110112
111113 /// <inheritdoc/>
@@ -165,37 +167,14 @@ public bool LinkWith(TLink linkObject, bool fromRemote = false)
165167
166168 LinkObject = linkObject ;
167169
168- return EstablishLinkWith ( linkObject , fromRemote ) ;
170+ return EstablishLink ( fromRemote ) ;
169171 }
170172
171- /// <summary>
172- /// Creates a link for the given sync value of the given name.
173- /// </summary>
174- /// <remarks>
175- /// <i>By default:</i> Calls
176- /// <c><paramref name="syncValue"/>.<see cref="IUnlinkedMonkeySyncValue{TLink}.EstablishLinkFor">EstablishLinkFor</see>()</c>.
177- /// </remarks>
178- /// <param name="propertyName">The name of the sync value to link.</param>
179- /// <param name="syncValue">The sync value to link.</param>
180- /// <param name="fromRemote">Whether the link is being established from the remote side.</param>
181- /// <returns><c>true</c> if the link was successfully created; otherwise, <c>false</c>.</returns>
182- protected virtual bool EstablishLinkFor ( string propertyName , TSyncValue syncValue , bool fromRemote )
183- => syncValue . EstablishLinkFor ( this , propertyName , fromRemote ) ;
184-
185- /// <summary>
186- /// Creates a link for the given sync method of the given name.
187- /// </summary>
188- /// <param name="methodName">The name of the sync method to link.</param>
189- /// <param name="syncMethod">The sync method to link.</param>
190- /// <param name="fromRemote">Whether the link is being established from the remote side.</param>
191- /// <returns><c>true</c> if the link was successfully created; otherwise, <c>false</c>.</returns>
192- protected abstract bool EstablishLinkFor ( string methodName , Action < TSyncObject > syncMethod , bool fromRemote ) ;
193-
194173 /// <remarks><para>
195174 /// <i>By default:</i> Sets up the <see cref="INotifyValueChanged.Changed"/> event handlers
196- /// and calls <see cref="EstablishLinkFor(string, TSyncValue , bool)">EstablishLinkFor</see>
175+ /// and calls <see cref="EstablishLinkFor(TSyncValue, string , bool)">EstablishLinkFor</see>
197176 /// for every readable <typeparamref name="TSyncValue"/> instance property and
198- /// <see cref="EstablishLinkFor(string, TSyncValue , bool)">its overload</see> for every
177+ /// <see cref="EstablishLinkFor(TSyncValue, string , bool)">its overload</see> for every
199178 /// <see cref="MonkeySyncMethodAttribute">MonkeySync method</see> on <typeparamref name="TSyncObject"/>.<br/>
200179 /// If the link is successfully created, this linked sync object will be
201180 /// <see cref="MonkeySyncRegistry.RegisterLinkedSyncObject{TLink}">added</see>
@@ -211,7 +190,7 @@ protected virtual bool EstablishLinkFor(string propertyName, TSyncValue syncValu
211190 /// </para>
212191 /// </remarks>
213192 /// <inheritdoc cref="LinkWith"/>
214- protected virtual bool EstablishLinkWith ( TLink linkObject , bool fromRemote )
193+ protected virtual bool EstablishLink ( bool fromRemote )
215194 {
216195 var success = true ;
217196
@@ -222,18 +201,41 @@ protected virtual bool EstablishLinkWith(TLink linkObject, bool fromRemote)
222201 syncValue . Changed += ( sender , changedArgs )
223202 => OnPropertyChanged ( syncValueProperty . Key ) ;
224203
225- success &= EstablishLinkFor ( syncValueProperty . Key , syncValue , fromRemote ) ;
204+ success &= EstablishLinkFor ( syncValue , syncValueProperty . Key , fromRemote ) ;
226205 }
227206
228207 foreach ( var syncMethod in methodsByName )
229- success &= EstablishLinkFor ( syncMethod . Key , syncMethod . Value , fromRemote ) ;
208+ success &= EstablishLinkFor ( syncMethod . Value , syncMethod . Key , fromRemote ) ;
230209
231210 if ( success )
232211 MonkeySyncRegistry . RegisterLinkedSyncObject ( this ) ;
233212
234213 return success ;
235214 }
236215
216+ /// <summary>
217+ /// Creates a link for the given sync value of the given name.
218+ /// </summary>
219+ /// <remarks>
220+ /// <i>By default:</i> Calls
221+ /// <c><paramref name="syncValue"/>.<see cref="IUnlinkedMonkeySyncValue{TLink}.EstablishLinkFor">EstablishLinkFor</see>()</c>.
222+ /// </remarks>
223+ /// <param name="syncValue">The sync value to link.</param>
224+ /// <param name="propertyName">The name of the sync value to link.</param>
225+ /// <param name="fromRemote">Whether the link is being established from the remote side.</param>
226+ /// <returns><c>true</c> if the link was successfully created; otherwise, <c>false</c>.</returns>
227+ protected virtual bool EstablishLinkFor ( TSyncValue syncValue , string propertyName , bool fromRemote )
228+ => syncValue . EstablishLinkFor ( this , propertyName , fromRemote ) ;
229+
230+ /// <summary>
231+ /// Creates a link for the given sync method of the given name.
232+ /// </summary>
233+ /// <param name="syncMethod">The sync method to link.</param>
234+ /// <param name="methodName">The name of the sync method to link.</param>
235+ /// <param name="fromRemote">Whether the link is being established from the remote side.</param>
236+ /// <returns><c>true</c> if the link was successfully created; otherwise, <c>false</c>.</returns>
237+ protected abstract bool EstablishLinkFor ( Action < TSyncObject > syncMethod , string methodName , bool fromRemote ) ;
238+
237239 /// <summary>
238240 /// Cleans up any managed resources as part of <see cref="Dispose()">disposing</see>.
239241 /// </summary>
@@ -267,7 +269,11 @@ protected void OnLinkInvalidated()
267269 if ( ! IsLinkValid && TryRestoreLink ( ) && IsLinkValid )
268270 return ;
269271
270- Invalidated . TryInvokeAll ( ) ;
272+ try
273+ {
274+ Invalidated . TryInvokeAll ( ) ;
275+ }
276+ catch { }
271277
272278 Dispose ( ) ;
273279 }
@@ -288,9 +294,9 @@ protected void OnPropertyChanged(string propertyName)
288294 }
289295
290296 /// <remarks><para>
291- /// <i>By default:</i> Calls <see cref="TryRestoreLinkFor(string, TSyncValue )">TryRestoreLinkFor</see>
297+ /// <i>By default:</i> Calls <see cref="TryRestoreLinkFor(TSyncValue, string )">TryRestoreLinkFor</see>
292298 /// for every readable <typeparamref name="TSyncValue"/> instance property and
293- /// <see cref="TryRestoreLinkFor(string, TSyncValue )">its overload</see> for every
299+ /// <see cref="TryRestoreLinkFor(TSyncValue, string )">its overload</see> for every
294300 /// <see cref="MonkeySyncMethodAttribute">MonkeySync method</see> on <typeparamref name="TSyncObject"/>.<br/>
295301 /// The detected properties are stored in <see cref="propertyAccessorsByName">propertyAccessorsByName</see>,
296302 /// while the detected methods are stored in <see cref="methodsByName">methodsByName</see>.
@@ -307,29 +313,31 @@ protected virtual bool TryRestoreLink()
307313 var success = true ;
308314
309315 foreach ( var syncValueProperty in propertyAccessorsByName )
310- success &= TryRestoreLinkFor ( syncValueProperty . Key , syncValueProperty . Value ( ( TSyncObject ) this ) ) ;
316+ success &= TryRestoreLinkFor ( syncValueProperty . Value ( ( TSyncObject ) this ) , syncValueProperty . Key ) ;
311317
312318 foreach ( var syncMethod in methodsByName )
313- success &= TryRestoreLinkFor ( syncMethod . Key , syncMethod . Value ) ;
319+ success &= TryRestoreLinkFor ( syncMethod . Value , syncMethod . Key ) ;
314320
315321 return success ;
316322 }
317323
324+ // Implement the sync value one through a method on sync values
325+
318326 /// <summary>
319327 /// Tries to restore the link for the given sync value of the given name.
320328 /// </summary>
321- /// <param name="propertyName">The name of the sync value to link.</param>
322329 /// <param name="syncValue">The sync value to link.</param>
330+ /// <param name="propertyName">The name of the sync value to link.</param>
323331 /// <returns><c>true</c> if the link was successfully restored; otherwise, <c>false</c>.</returns>
324- protected abstract bool TryRestoreLinkFor ( string propertyName , TSyncValue syncValue ) ;
332+ protected abstract bool TryRestoreLinkFor ( TSyncValue syncValue , string propertyName ) ;
325333
326334 /// <summary>
327335 /// Tries to restore the link for the given sync method of the given name.
328336 /// </summary>
329- /// <param name="methodName">The name of the sync method to link.</param>
330337 /// <param name="syncMethod">The sync method to link.</param>
338+ /// <param name="methodName">The name of the sync method to link.</param>
331339 /// <returns><c>true</c> if the link was successfully restored; otherwise, <c>false</c>.</returns>
332- protected abstract bool TryRestoreLinkFor ( string methodName , Action < TSyncObject > syncMethod ) ;
340+ protected abstract bool TryRestoreLinkFor ( Action < TSyncObject > syncMethod , string methodName ) ;
333341
334342 private void Dispose ( bool disposing )
335343 {
0 commit comments