Skip to content

Commit

Permalink
feat(Configuration): Support to use IOptionsSnapshot<TOptions> to get…
Browse files Browse the repository at this point in the history
… multi-node configuration (#225)
  • Loading branch information
zhenlei520 authored Sep 1, 2022
1 parent f25626d commit 3708059
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ public class ConfigurationRelationOptions
/// Object type of mapping node relationship
/// </summary>
public Type ObjectType { get; set; } = default!;

public string Name { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ internal static void AutoMapping(this MasaConfigurationBuilder builder, params A

var option = (IMasaConfigurationOptions)Activator.CreateInstance(optionType, !constructorInfo.IsPublic)!;
var sectionName = option.Section ?? optionType.Name;
if (builder.Relations.Any(relation => relation.SectionType == option.SectionType && relation.Section == sectionName && relation.ObjectType == optionType))
var name = Options.DefaultName;
if (builder.Relations.Any(relation => relation.SectionType == option.SectionType && relation.Section == sectionName && relation.ObjectType == optionType && relation.Name == name))
{
throw new ArgumentException(
"The section has been loaded, no need to load repeatedly, check whether there are duplicate sections or inheritance between auto-mapping classes");
Expand All @@ -40,7 +41,8 @@ internal static void AutoMapping(this MasaConfigurationBuilder builder, params A
SectionType = option.SectionType,
ParentSection = option.ParentSection,
Section = sectionName,
ObjectType = optionType
ObjectType = optionType,
Name = name
});
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public static IConfigurationRoot CreateMasaConfiguration(
sectionNames.AddRange(relation.Section!.Split(ConfigurationPath.KeyDelimiter));
}

services.ConfigureOption(configuration, sectionNames, relation.ObjectType);
services.ConfigureOption(configuration, sectionNames, relation.ObjectType, relation.Name);
});

return configuration;
Expand All @@ -83,7 +83,8 @@ private static void ConfigureOption(
this IServiceCollection services,
IConfiguration configuration,
List<string> sectionNames,
Type optionType)
Type optionType,
string name)
{
IConfigurationSection? configurationSection = null;
foreach (var sectionName in sectionNames)
Expand All @@ -97,19 +98,19 @@ private static void ConfigureOption(
throw new MasaException($"Check if the mapping section is correct,section name is [{configurationSection!.Path}]");

var configurationChangeTokenSource =
Activator.CreateInstance(typeof(ConfigurationChangeTokenSource<>).MakeGenericType(optionType), string.Empty,
Activator.CreateInstance(typeof(ConfigurationChangeTokenSource<>).MakeGenericType(optionType), name,
configurationSection)!;
services.TryAdd(new ServiceDescriptor(typeof(IOptionsChangeTokenSource<>).MakeGenericType(optionType),
services.Add(new ServiceDescriptor(typeof(IOptionsChangeTokenSource<>).MakeGenericType(optionType),
configurationChangeTokenSource));

Action<BinderOptions> configureBinder = _ =>
{
};
var configureOptions =
Activator.CreateInstance(typeof(NamedConfigureFromConfigurationOptions<>).MakeGenericType(optionType),
string.Empty,
name,
configurationSection, configureBinder)!;
services.TryAdd(new ServiceDescriptor(typeof(IConfigureOptions<>).MakeGenericType(optionType),
services.Add(new ServiceDescriptor(typeof(IConfigureOptions<>).MakeGenericType(optionType),
configureOptions));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,22 @@ public class MasaRelationOptions
/// </summary>
/// <typeparam name="TModel"></typeparam>
/// <param name="section">The default is null, which is consistent with the mapping class name, and string.Empty when no root node exists</param>
/// <param name="name"></param>
/// <returns></returns>
public MasaRelationOptions MappingLocal<TModel>(string? section = null) where TModel : class
=> Mapping<TModel>(SectionTypes.Local, null!, section);
public MasaRelationOptions MappingLocal<TModel>(string? section = null, string? name = null) where TModel : class
=> Mapping<TModel>(SectionTypes.Local, null!, section, name);

/// <summary>
/// Map Section relationship By ConfigurationApi
/// </summary>
/// <typeparam name="TModel"></typeparam>
/// <param name="parentSection">The name of the parent section, if it is empty, it will be mounted under SectionType, otherwise it will be mounted to the specified section under SectionType</param>
/// <param name="section">The default is null, which is consistent with the mapping class name, and string.Empty when no root node exists</param>
/// <param name="name"></param>
/// <returns></returns>
public MasaRelationOptions MappingConfigurationApi<TModel>(string parentSection, string? section = null) where TModel : class
=> Mapping<TModel>(SectionTypes.ConfigurationApi, parentSection, section);
public MasaRelationOptions MappingConfigurationApi<TModel>(string parentSection, string? section = null, string? name = null)
where TModel : class
=> Mapping<TModel>(SectionTypes.ConfigurationApi, parentSection, section, name);

/// <summary>
/// Map Section relationship
Expand All @@ -33,21 +36,25 @@ public MasaRelationOptions MappingConfigurationApi<TModel>(string parentSection,
/// <param name="sectionType"></param>
/// <param name="parentSection">parent section, local section is the name of the locally configured section, and ConfigurationApi is the name of the Appid where the configuration is located</param>
/// <param name="section">The default is null, which is consistent with the mapping class name</param>
/// <param name="name"></param>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public MasaRelationOptions Mapping<TModel>(SectionTypes sectionType, string parentSection, string? section = null) where TModel : class
public MasaRelationOptions Mapping<TModel>(SectionTypes sectionType, string parentSection, string? section = null, string? name = null)
where TModel : class
{
name ??= Options.DefaultName;
section ??= typeof(TModel).Name;

if (Relations.Any(relation => relation.SectionType == sectionType && relation.Section == section))
if (Relations.Any(relation => relation.SectionType == sectionType && relation.Section == section && relation.Name == name))
throw new ArgumentOutOfRangeException(nameof(section), "The current section already has a configuration");

Relations.Add(new ConfigurationRelationOptions()
{
SectionType = sectionType,
ParentSection = parentSection,
Section = section,
ObjectType = typeof(TModel)
ObjectType = typeof(TModel),
Name = name
});
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,4 +308,31 @@ public void TestMasaConfigurationByKey(string key, string value)
var localConfiguration = builder.GetMasaConfiguration().Local;
Assert.IsTrue(localConfiguration[key] == value);
}

[TestMethod]
public void TestMasaConfigurationByName()
{
var builder = WebApplication.CreateBuilder();
builder.AddMasaConfiguration(configurationBuilder =>
{
configurationBuilder.AddJsonFile("customAppConfig.json", true, true)
.AddJsonFile("rabbitMq.json", true, true);
configurationBuilder.UseMasaOptions(option =>
{
option.MappingLocal<RedisOptions>();
option.MappingLocal<RedisOptions>("RedisOptions2", "RedisOptions2");
});
}, typeof(ConfigurationTest).Assembly);
var serviceProvider = builder.Services.BuildServiceProvider();
var options = serviceProvider.GetService<IOptionsSnapshot<RedisOptions>>();
Assert.IsNotNull(options);
Assert.AreEqual("localhost", options.Value.Ip);
Assert.AreEqual("", options.Value.Password);
Assert.AreEqual(6379, options.Value.Port);

var options2 = options.Get("RedisOptions2");
Assert.AreEqual("127.0.0.1", options2.Ip);
Assert.AreEqual("123456", options2.Password);
Assert.AreEqual(6378, options2.Port);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,10 @@
"Ip": "localhost",
"Password": "",
"Port": 6379
},
"RedisOptions2": {
"Ip": "127.0.0.1",
"Password": "123456",
"Port": 6378
}
}

0 comments on commit 3708059

Please sign in to comment.