Skip to content

Instantly share code, notes, and snippets.

@Carl-Hugo
Last active October 25, 2020 22:03
Show Gist options
  • Save Carl-Hugo/161d2948d430028f0cb07442ab17c740 to your computer and use it in GitHub Desktop.
Save Carl-Hugo/161d2948d430028f0cb07442ab17c740 to your computer and use it in GitHub Desktop.
2020-10-25-Options-DavidF
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.0-rc.2.20475.5" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0-rc.2.20475.5" />
<PackageReference Include="Xunit" Version="2.4.1" />
</ItemGroup>
</Project>
//
// To run: `dotnet run` (should display `All Good!`)
// Requires .NET 5 SDK
// Uses C# 9 preview features
//
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Xunit;
var services = new ServiceCollection();
// Configure MyOptions and consumers
services.Configure<MyOptions>(x => new MyOptions { Name = "Whatever" });
services.Configure<MyOptions>("MagicName", x => new MyOptions { Name = "MagicName" });
services.AddTransient<MeControlOptionsLifetimeSingleton>();
services.AddTransient<MeControlOptionsLifetimeScoped>();
services.AddTransient<MeDontControlOptionsLifetime>();
services.AddTransient<MeControlOptionName>();
// This is an example of how to bind MyOptions to an "IOptionsWhatever<T>"
// This could be anything that would make sense for any given concrete scenario
services.AddTransient<MyOptions>(sp => sp.GetRequiredService<IOptionsMonitor<MyOptions>>().CurrentValue);
// Using the registered stuff just for fun :)
var serviceProvider = services.BuildServiceProvider();
var meControlOptionsLifetimeSingleton = serviceProvider.GetRequiredService<MeControlOptionsLifetimeSingleton>();
var meControlOptionsLifetimeScoped = serviceProvider.GetRequiredService<MeControlOptionsLifetimeScoped>();
var meDontControlOptionsLifetime = serviceProvider.GetRequiredService<MeDontControlOptionsLifetime>();
var meControlOptionName = serviceProvider.GetRequiredService<MeControlOptionName>();
// Making sure that all is rigged correctly (while at it)
Assert.Same(meControlOptionsLifetimeSingleton.Options.CurrentValue, meDontControlOptionsLifetime.Options);
Assert.NotSame(meControlOptionsLifetimeSingleton.Options.CurrentValue, meControlOptionsLifetimeScoped.Options.Value);
Assert.NotSame(meControlOptionName.Options, meControlOptionsLifetimeSingleton.Options.CurrentValue);
Console.WriteLine("All Good!");
// Some options
public class MyOptions
{
public string Name { get; set; }
}
// This class controls the lifetime of its MyOptions dependency.
// By injecting a IOptionsMonitor<T>, MeControlOptionsLifetimeSingleton decides that it wants a singleton lifetime.
// To change the lifetime of that MyOptions, we must update MeControlOptionsLifetimeSingleton
// Not IoC
public record MeControlOptionsLifetimeSingleton(IOptionsMonitor<MyOptions> Options);
// This class controls the lifetime of its MyOptions dependency.
// By injecting a IOptionsSnapshot<T>, MeControlOptionsLifetimeScoped decides that it wants a scoped lifetime.
// To change the lifetime of that MyOptions, we must update MeControlOptionsLifetimeScoped
// Not IoC
public record MeControlOptionsLifetimeScoped(IOptionsSnapshot<MyOptions> Options);
// This class don't control the lifetime of its MyOptions dependency.
// By injecting MyOptions directly, MeDontControlOptionsLifetime lets the composition root manage the MyOptions's lifetime.
// To change the lifetime of that MyOptions, we must update the composition root (a good thing)
// Yes: IoC
public record MeDontControlOptionsLifetime(MyOptions Options);
// This class controls the lifetime of its MyOptions dependency.
// This class controls what instance of MyOptions is "created" (by name).
// To change the lifetime of that MyOptions, we must update MeControlOptionName
// To change the created instance of MyOptions, we must update MeControlOptionName (change "MagicName" by something else)
// Not IoC
public class MeControlOptionName
{
public MyOptions Options { get; }
public MeControlOptionName(IOptionsFactory<MyOptions> factory)
{
Options = factory.Create("MagicName");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment