Skip to content

Commit 8202784

Browse files
committed
Updates
1 parent 50c2ca9 commit 8202784

File tree

1 file changed

+38
-34
lines changed

1 file changed

+38
-34
lines changed

aspnetcore/blazor/components/cascading-values-and-parameters.md

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -139,60 +139,64 @@ public class NotifyingDalek : INotifyPropertyChanged
139139
}
140140
```
141141

142-
The following `CascadingValueSourceFactory` has a `CreateNotifying` method to create a <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601> from a type that implements <xref:System.ComponentModel.INotifyPropertyChanged>.
142+
The following `CascadingValueServiceCollectionExtensions` creates a <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601> from a type that implements <xref:System.ComponentModel.INotifyPropertyChanged>.
143143

144-
`CascadingValueSourceFactory.cs`:
144+
`CascadingValueServiceCollectionExtensions.cs`:
145145

146146
```csharp
147-
using Microsoft.AspNetCore.Components;
148147
using System.ComponentModel;
148+
using Microsoft.AspNetCore.Components;
149149

150-
public static class CascadingValueSourceFactory
151-
{
152-
public static NotifyingCascadingValueSource<T> CreateNotifying<T>(
153-
T value, bool isFixed = false) where T : INotifyPropertyChanged
154-
{
155-
return new NotifyingCascadingValueSource<T>(value, isFixed);
156-
}
157-
}
150+
namespace Microsoft.Extensions.DependencyInjection;
158151

159-
public class NotifyingCascadingValueSource<T> : IDisposable where T : INotifyPropertyChanged
152+
public static class CascadingApplicationStateServiceCollectionExtensions
160153
{
161-
private readonly T value;
162-
private readonly CascadingValueSource<T> source;
163-
164-
public NotifyingCascadingValueSource(T value, bool isFixed = false)
154+
public static IServiceCollection AddCascadingApplicationState<T>(
155+
this IServiceCollection serviceCollection, T value, bool isFixed = false)
156+
where T : INotifyPropertyChanged
165157
{
166-
this.value = value;
167-
source = new CascadingValueSource<T>(value, isFixed);
168-
this.value.PropertyChanged += OnValuePropertyChanged;
158+
return serviceCollection.AddCascadingValue<T>(services =>
159+
{
160+
return new ApplicationStateCascadingValueSource<T>(value, isFixed);
161+
});
169162
}
170163

171-
private void OnValuePropertyChanged(object? sender, PropertyChangedEventArgs e)
164+
private sealed class ApplicationStateCascadingValueSource<T>
165+
: CascadingValueSource<T>, IDisposable where T : INotifyPropertyChanged
172166
{
173-
_ = source.NotifyChangedAsync();
174-
}
167+
private readonly T value;
168+
private readonly CascadingValueSource<T> source;
175169

176-
public CascadingValueSource<T> Source => source;
170+
public ApplicationStateCascadingValueSource(T value, bool isFixed = false)
171+
: base(value, isFixed = false)
172+
{
173+
this.value = value;
174+
source = new CascadingValueSource<T>(value, isFixed);
175+
this.value.PropertyChanged += HandlePropertyChanged;
176+
}
177177

178-
public void Dispose()
179-
{
180-
value.PropertyChanged -= OnValuePropertyChanged;
178+
private void HandlePropertyChanged(object? sender, PropertyChangedEventArgs e)
179+
{
180+
_ = NotifyChangedAsync();
181+
}
182+
183+
public CascadingValueSource<T> Source => source;
181184

182-
// The following prevents derived types that introduce a
183-
// finalizer from needing to re-implement IDisposable.
184-
GC.SuppressFinalize(this);
185+
public void Dispose()
186+
{
187+
value.PropertyChanged -= HandlePropertyChanged;
188+
}
185189
}
186190
}
187191
```
188192

189-
The type's <xref:System.ComponentModel.PropertyChangedEventHandler> (`PropertyChanged`) calls the <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601>'s <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601.NotifyChangedAsync%2A> method to notify subscribers that the cascading value has changed. The <xref:System.Threading.Tasks.Task> is discarded when calling <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601.NotifyChangedAsync%2A> because the call only represents the duration of the dispatch to the synchronous context. Exceptions are handled internally by dispatching them to the renderer within the context of whichever component threw when receiving the update. This is the same way that exceptions are processed with a <xref:Microsoft.AspNetCore.Components.CascadingValue%601>, which isn't notified about exceptions that happen inside notification recipients.
193+
The type's <xref:System.ComponentModel.PropertyChangedEventHandler> (`HandlePropertyChanged`) calls the <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601>'s <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601.NotifyChangedAsync%2A> method to notify subscribers that the cascading value has changed. The <xref:System.Threading.Tasks.Task> is discarded when calling <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601.NotifyChangedAsync%2A> because the call only represents the duration of the dispatch to the synchronous context. Exceptions are handled internally by dispatching them to the renderer within the context of whichever component threw when receiving the update. This is the same way that exceptions are processed with a <xref:Microsoft.AspNetCore.Components.CascadingValue%601>, which isn't notified about exceptions that happen inside notification recipients. The event handler is disconnected in the `Dispose` method to prevent a memory leak.
190194

191-
In the `Program` file&dagger;, `NotifyingDalek` is created as a <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601> with an initial `Unit` value of 888 units:
195+
In the `Program` file&dagger;, `NotifyingDalek` is passed to create a <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601> with an initial `Unit` value of 888 units:
192196

193197
```csharp
194-
builder.Services.AddCascadingValue(
195-
s => CascadingValueSourceFactory.CreateNotifying(new NotifyingDalek() { Units = 888 }));
198+
builder.Services.AddCascadingApplicationState<NotifyingDalek>(
199+
new NotifyingDalek() { Units = 888 });
196200
```
197201

198202
> [!NOTE]
@@ -272,7 +276,7 @@ To demonstrate multiple subscriber notifications, the following `DaleksMain` com
272276
<Daleks />
273277
```
274278

275-
Because the <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601>'s type in this example is a class type, you can meet virtually any state management feature specification requirement. However, subscriptions create overhead and reduce performance, so benchmark the performance of this approach in your app and compare it to other [state management approaches](xref:blazor/state-management) before adopting it in a production app with constrained processing and memory resources.
279+
Because the <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601>'s type in this example (`NotifyingDalek`) is a class type, you can meet virtually any state management feature specification requirement. However, subscriptions create overhead and reduce performance, so benchmark the performance of this approach in your app and compare it to other [state management approaches](xref:blazor/state-management) before adopting it in a production app with constrained processing and memory resources.
276280

277281
:::moniker-end
278282

0 commit comments

Comments
 (0)