Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions docs/core/extensions/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,46 @@ builder.Services

In the preceding code, the `Configure<TOptions>` method is used to register a configuration instance that `TOptions` will bind against, and updates the options when the configuration changes.

### Performance considerations

`IOptionsSnapshot<T>` recomputes the options instance on every new scope by
re-running the full configuration pipeline (`IConfigureOptions<T>`,
`IConfigureNamedOptions<T>`, `IPostConfigureOptions<T>`, `IValidateOptions<T>`,
and any `IConfiguration` binding registered via `Configure<T>(section)`). It
does this whether or not the underlying configuration has actually changed, and
once per named instance resolved in that scope.

In ASP.NET Core, a scope corresponds to a single HTTP request, so this cost is
paid on the request hot path. For options whose binding or post-configuration is
non-trivial (large or deeply nested configuration sections, expensive
`PostConfigure`, validation, and so on), this can add measurable per-request
overhead.

Consider the following alternatives:

- If you don't need the value to change after the app starts, prefer
`IOptions<T>`. It's a singleton and the value is computed once for the
lifetime of the app.
- If you need to observe configuration changes but want to avoid rebuilding
options on every scope, prefer `IOptionsMonitor<T>`. It's a singleton that
caches the options instance and only rebuilds when the underlying configuration
emits a change notification. Steady-state reads of `CurrentValue` or
`Get(name)` are cache hits.

If you still need snapshot semantics (a value guaranteed not to change within a
scope) but want to avoid the per-scope rebuild cost, you can layer on top of
`IOptionsMonitor<T>` in one of two ways:

- Capture `monitor.CurrentValue` once at the start of the scope and read it
from there for the rest of the scope.
- Register the options type as scoped with a factory:

```csharp
services.AddScoped(sp =>
sp.GetRequiredService<IOptionsMonitor<MyOptions>>().CurrentValue);
```


## IOptionsMonitor

The `IOptionsMonitor` type supports change notifications and enables scenarios where your app may need to respond to configuration source changes dynamically. This is useful when you need to react to changes in configuration data after the app has started. Change notifications are only supported for file-system based configuration providers, such as the following:
Expand Down
36 changes: 36 additions & 0 deletions docs/framework/migration-guide/retargeting/4.5.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,42 @@ This article lists the app compatibility issues that were introduced in .NET Fra

[!INCLUDE[EncoderParameter ctor is obsolete](~/includes/migration-guide/retargeting/winforms/encoderparameter-ctor-obsolete.md)]

#### Default SubsystemVersion changed from 4.00 to 6.00

| | Value |
|---|---|
| **Scope** | Minor |
| **Version introduced** | 4.5 |
| **Type of change** | Retargeting |

##### Details

Starting with .NET Framework 4.5, the C# and Visual Basic compilers set the default `SubsystemVersion` of compiled executables to `6.00`, up from the previous default of `4.00`. This change enables Windows features introduced in Windows Vista, such as improved virtual memory handling and DPI awareness per monitor.

A `SubsystemVersion` of `6.00` signals to Windows that the application supports higher-resolution DPI modes, which causes the operating system to return different values from several Windows API calls (including `GetSystemMetrics`). As a result, properties of the <xref:System.Windows.Forms.SystemInformation> class that are backed by `GetSystemMetrics`—such as <xref:System.Windows.Forms.SystemInformation.FixedFrameBorderSize>, <xref:System.Windows.Forms.SystemInformation.FrameBorderSize>, and related metrics—may return values that differ from those returned under .NET Framework 4.0. This can cause layout issues in applications that manually calculate or set form sizes using these properties.

This change only affects applications that target .NET Framework 4.5 or later. Applications that target .NET Framework 4.0 are not affected.

##### Suggestion

If your application experiences unexpected WinForms window sizing or layout issues after migrating to .NET Framework 4.5 or later, you can restore the previous behavior by explicitly setting `SubsystemVersion` to `4.00` in your project file:

```xml
<PropertyGroup>
<SubsystemVersion>4.00</SubsystemVersion>
</PropertyGroup>
```

> [!NOTE]
> Setting `SubsystemVersion` to `4.00` opts out of certain Windows Vista and later features. Evaluate the trade-offs for your application before applying this workaround.

##### References

- [Form height and width changes with Visual Studio 2012](https://learn.microsoft.com/previous-versions/troubleshoot/dotnet/framework/wrong-winform-height-width)
- [Advanced C# compiler options - SubsystemVersion](https://learn.microsoft.com/dotnet/csharp/language-reference/compiler-options/advanced#subsystemversion)
- <xref:System.Windows.Forms.SystemInformation>


### Windows Communication Foundation (WCF)

[!INCLUDE [onwritebodycontents-change](~/includes/migration-guide/retargeting/wcf/onwritebodycontents-change.md)]
Expand Down
Loading