I basically have this code
[Fact]
public async Task Test()
{
var settings = new MySettings() { Name = "Jhon" }; //<-- use this
var webHostBuilder = new WebHostBuilder()
.UseStartup<TestStartup>()
.ConfigureServices(services =>
{
// this is called...
services.AddSingleton(settings);
});
//omitted code..
}
And I want to be able to use MySettings
in the TestStartup
.
Whatever I try just returns Name == null
..
I have tried this
public class TestStartup : Startup
{
public TestStartup(IConfiguration configuration) : base(configuration)
{
Configuration = configuration;
// Name is always != "Jhon"
// doesn't work
var mySettings = configuration.Get<MySettings>();
// doesn't work either
var mySettings = new MySettings();
configuration.Bind("MySettings", mySettings);
// tried various other things that didn't work
}
}
What am I missing?
You can leverage the MemoryConfigurationProvider
:
using Microsoft.Extensions.Configuration;
var webHostBuilder = new WebHostBuilder()
.ConfigureAppConfiguration(configurationBuilder => configurationBuilder
.AddInMemoryCollection(new Dictionary<string, string?>
{
{ "Name", "Jhon" },
{"Logging:LogLevel:Default", "Warning"}
}))
.UseStartup<TestStartup>()
// ...
and then it can be consumed with any standard pattern for configuration, for example:
public class TestStartup : Startup
{
public TestStartup(IConfiguration configuration) : base(configuration)
{
var nameKeyValue = Configuration["Name"];
}
}
If you wanted to pass a whole class over it could be done with this helper
public static class TestHelpers<T> where T : new()
{
/// <summary>
/// Helper class to convert an object of type T to a dictionary.
/// </summary>
/// <param name="objectToConvert"></param>
/// <returns></returns>
public static Dictionary<string, string?> ConvertObjectToDictionary(T objectToConvert)
{
var dictionary = new Dictionary<string, string?>();
foreach (var property in objectToConvert.GetType().GetProperties())
{
var value = property.GetValue(objectToConvert);
dictionary.Add(property.Name, value?.ToString());
}
return dictionary;
}
/// <summary>
/// Helper class to convert a dictionary back to an object of type T.
/// </summary>
/// <param name="configDictionary"></param>
/// <returns></returns>
public static T ConvertDictionaryToObject(Dictionary<string, string> configDictionary)
{
var objectToPopulate = new T();
var properties = objectToPopulate.GetType().GetProperties();
foreach (var property in properties)
{
if (configDictionary.ContainsKey(property.Name))
{
var value = configDictionary[property.Name];
if (value != null)
{
try
{
property.SetValue(objectToPopulate, Convert.ChangeType(value, property.PropertyType));
}
catch (Exception ex)
{
// swallow exception for private properties. This could be logged out
}
}
}
}
return objectToPopulate;
}
}
and use it like this
var settings = new MySettings() { Name = "Jhon" };
// convert the class to dictionary
var mySettingsDictionary= TestHelpers<MySettings>.ConvertObjectToDictionary(settings);
// and convert it back to class
var mySettingsClass= TestHelpers<MySettings>.ConvertDictionaryToObject(mySettingsDictionary);
// and in the TestStartup like this
var mySettingsClass= TestHelpers<MySettings>.ConvertDictionaryToObject(Configuration.AsEnumerable().ToDictionary(x => x.Key, x => x.Value))