Skip to content

Commit b6c3adf

Browse files
committed
Configuration reading based on IConfigurationSectionReader implementations
1 parent 6759bb3 commit b6c3adf

6 files changed

Lines changed: 294 additions & 281 deletions

File tree

Extensions/Xtensive.Orm.Localization/Configuration/LocalizationConfiguration.cs

Lines changed: 16 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Threading;
1212
using Microsoft.Extensions.Configuration;
1313
using Xtensive.Core;
14+
using Xtensive.Orm.Configuration;
1415

1516
namespace Xtensive.Orm.Localization.Configuration
1617
{
@@ -38,7 +39,7 @@ private class LocalizationOptions
3839
/// Gets or sets the default culture.
3940
/// </summary>
4041
/// <value>The default culture.</value>
41-
public CultureInfo DefaultCulture { get; private set; }
42+
public CultureInfo DefaultCulture { get; internal set; }
4243

4344
/// <summary>
4445
/// Loads the <see cref="LocalizationConfiguration"/>
@@ -114,90 +115,30 @@ private static LocalizationConfiguration GetConfigurationFromSection(Configurati
114115
return result;
115116
}
116117

118+
/// <summary>
119+
/// Loads <see cref="LocalizationConfiguration"/> from given configuration section.
120+
/// </summary>
121+
/// <param name="configurationSection"><see cref="IConfigurationSection"/> to load from.</param>
122+
/// <returns>Loaded configuration or default configuration if loading failed for some reason.</returns>
117123
public static LocalizationConfiguration Load(IConfigurationSection configurationSection)
118124
{
119125
ArgumentValidator.EnsureArgumentNotNull(configurationSection, nameof(configurationSection));
120126

121-
if (TryReadAsOptions(configurationSection, out var localizationConfiguration))
122-
return localizationConfiguration;
123-
124-
// if failed then try to handle unusual formats or xml with name attribute
125-
return TryReadUnusualOrOldFormats(configurationSection, out var fallbackConfiguration)
126-
? fallbackConfiguration
127-
: new LocalizationConfiguration {
128-
DefaultCulture = Thread.CurrentThread.CurrentCulture
129-
};
130-
}
131-
132-
private static bool TryReadAsOptions(IConfigurationSection rootSection, out LocalizationConfiguration localizationConfiguration)
133-
{
134-
LocalizationOptions localizationOptions;
135-
try {
136-
localizationOptions = rootSection.Get<LocalizationOptions>();
137-
}
138-
catch {
139-
localizationConfiguration = null;
140-
return false;
141-
}
142-
143-
if (localizationOptions != null) {
144-
if (!string.IsNullOrEmpty(localizationOptions.DefaultCulture)) {
145-
try {
146-
var culture = new CultureInfo(localizationOptions.DefaultCulture);
147-
localizationConfiguration = new LocalizationConfiguration() { DefaultCulture = culture };
148-
return true;
149-
}
150-
catch (CultureNotFoundException) {
151-
}
152-
}
153-
}
154-
localizationConfiguration = null;
155-
return false;
127+
return new LocalizationConfigurationReader().Read(configurationSection);
156128
}
157129

158130
/// <summary>
159-
/// Tries to read configuration of old format that supported by
160-
/// old <see cref="System.Configuration.ConfigurationManager"/>
161-
/// or configuration where name of service is element, not attribute.
131+
/// Loads <see cref="LocalizationConfiguration"/> from given configuration section of <paramref name="configurationRoot"/>.
132+
/// If section name is not provided <see cref="LocalizationConfiguration.DefaultSectionName"/> is used.
162133
/// </summary>
163-
/// <param name="rootSection">A configuration section that contains data to read.</param>
164-
/// <param name="localizationConfiguration">Read configuration or null if reading was not successful.</param>
165-
/// <returns><see landword="true"/> if reading is successful, otherwise <see landword="true"/>.</returns>
166-
private static bool TryReadUnusualOrOldFormats(IConfigurationSection rootSection,
167-
out LocalizationConfiguration localizationConfiguration)
134+
/// <param name="configurationRoot"><see cref="IConfigurationRoot"/> of sections.</param>
135+
/// <param name="sectionName">Custom section name to load from.</param>
136+
/// <returns>Loaded configuration or default configuration if loading failed for some reason.</returns>
137+
public static LocalizationConfiguration Load(IConfigurationRoot configurationRoot, string sectionName = null)
168138
{
169-
var defaultCultureSection = rootSection.GetSection(DefaultCultureElementName);
170-
171-
if (defaultCultureSection == null) {
172-
localizationConfiguration = null;
173-
return false;
174-
}
175-
176-
var cultureName = defaultCultureSection.GetSection(CultureNameAttributeName)?.Value;
177-
if (cultureName == null) {
178-
var children = defaultCultureSection.GetChildren().ToList();
179-
if (children.Count > 0) {
180-
cultureName = children[0].GetSection(CultureNameAttributeName).Value;
181-
}
182-
}
139+
ArgumentValidator.EnsureArgumentNotNull(configurationRoot, nameof(configurationRoot));
183140

184-
if (cultureName != null && ! string.IsNullOrEmpty(cultureName)) {
185-
try {
186-
var culture = new CultureInfo(cultureName);
187-
localizationConfiguration = new LocalizationConfiguration() {
188-
DefaultCulture = culture
189-
};
190-
return true;
191-
}
192-
catch (CultureNotFoundException) {
193-
localizationConfiguration = new LocalizationConfiguration() {
194-
DefaultCulture = Thread.CurrentThread.CurrentCulture
195-
};
196-
return true;
197-
}
198-
}
199-
localizationConfiguration = null;
200-
return false;
141+
return new LocalizationConfigurationReader().Read(configurationRoot, sectionName ?? DefaultSectionName);
201142
}
202143
}
203144
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright (C) 2011-2024 Xtensive LLC.
2+
// All rights reserved.
3+
// For conditions of distribution and use, see license.
4+
// Created by: Dmitri Maximov
5+
// Created: 2012.07.06
6+
7+
using System;
8+
using System.Globalization;
9+
using System.Linq;
10+
using System.Threading;
11+
using Microsoft.Extensions.Configuration;
12+
using Xtensive.Core;
13+
using Xtensive.Orm.Configuration;
14+
15+
namespace Xtensive.Orm.Localization.Configuration
16+
{
17+
internal sealed class LocalizationConfigurationReader : IConfigurationSectionReader<LocalizationConfiguration>
18+
{
19+
public LocalizationConfiguration Read(IConfigurationSection configurationSection) => ReadInternal(configurationSection);
20+
21+
public LocalizationConfiguration Read(IConfigurationSection configurationSection, string nameOfConfiguration) =>
22+
throw new NotSupportedException();
23+
24+
public LocalizationConfiguration Read(IConfigurationRoot configurationRoot) =>
25+
Read(configurationRoot, LocalizationConfiguration.DefaultSectionName);
26+
27+
public LocalizationConfiguration Read(IConfigurationRoot configurationRoot, string sectionName)
28+
{
29+
var section = configurationRoot.GetSection(sectionName);
30+
return ReadInternal(section);
31+
}
32+
33+
public LocalizationConfiguration Read(IConfigurationRoot configurationRoot, string sectionName, string nameOfConfiguration) =>
34+
throw new NotSupportedException();
35+
36+
private const string DefaultCultureElementName = "DefaultCulture";
37+
private const string CultureNameAttributeName = "name";
38+
39+
private LocalizationConfiguration ReadInternal(IConfigurationSection configurationSection)
40+
{
41+
var defaultCultureSection = configurationSection.GetSection(DefaultCultureElementName);
42+
if (defaultCultureSection == null)
43+
return new LocalizationConfiguration() { DefaultCulture = Thread.CurrentThread.CurrentCulture };
44+
45+
var cultureName = defaultCultureSection.Value;
46+
if (cultureName == null) {
47+
cultureName = defaultCultureSection.GetSection(CultureNameAttributeName)?.Value;
48+
if (cultureName == null) {
49+
var children = defaultCultureSection.GetChildren().ToList();
50+
if (children.Count > 0) {
51+
cultureName = children[0].GetSection(CultureNameAttributeName).Value;
52+
}
53+
}
54+
}
55+
56+
if (cultureName.IsNullOrEmpty())
57+
return new LocalizationConfiguration() { DefaultCulture = Thread.CurrentThread.CurrentCulture };
58+
try {
59+
return new LocalizationConfiguration() { DefaultCulture = new CultureInfo(cultureName) };
60+
}
61+
catch (CultureNotFoundException) {
62+
return new LocalizationConfiguration() { DefaultCulture = Thread.CurrentThread.CurrentCulture };
63+
}
64+
}
65+
}
66+
}

Extensions/Xtensive.Orm.Reprocessing/Configuration/ReprocessingConfiguration.cs

Lines changed: 11 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Configuration;
33
using Microsoft.Extensions.Configuration;
44
using Xtensive.Core;
5+
using Xtensive.Orm.Configuration;
56

67
namespace Xtensive.Orm.Reprocessing.Configuration
78
{
@@ -10,14 +11,6 @@ namespace Xtensive.Orm.Reprocessing.Configuration
1011
/// </summary>
1112
public class ReprocessingConfiguration
1213
{
13-
// intermediate class for reading section
14-
private class ReprocessingOptions
15-
{
16-
public string DefaultTransactionOpenMode { get; set; }
17-
18-
public string DefaultExecuteStrategy { get; set; }
19-
}
20-
2114
/// <summary>
2215
/// Gets default value of the <see cref="DefaultTransactionOpenMode"/> property.
2316
/// </summary>
@@ -99,40 +92,20 @@ public static ReprocessingConfiguration Load(IConfigurationSection configuration
9992
{
10093
ArgumentValidator.EnsureArgumentNotNull(configurationSection, nameof(configurationSection));
10194

102-
return TryReadAsOptions(configurationSection, out var reprocessingConfiguration)
103-
? reprocessingConfiguration
104-
: new ReprocessingConfiguration();
95+
return new ReprocessingConfigurationReader().Read(configurationSection);
10596
}
10697

107-
private static bool TryReadAsOptions(IConfigurationSection configuration, out ReprocessingConfiguration reprocessingConfiguration)
98+
/// <summary>
99+
/// Loads the <see cref="ReprocessingConfiguration"/> from specified section of configuration root.
100+
/// </summary>
101+
/// <param name="configurationRoot"><see cref="IConfigurationRoot"/> to load section from.</param>
102+
/// <param name="sectionName">Name of the section where configuration is stored.</param>
103+
/// <returns>Loaded configuration or configuration with default settings.</returns>
104+
public static ReprocessingConfiguration Load(IConfigurationRoot configurationRoot, string sectionName = null)
108105
{
109-
var reprocessingOptions = configuration.Get<ReprocessingOptions>();
110-
111-
if (reprocessingOptions == default) {
112-
reprocessingConfiguration = null;
113-
return false;
114-
}
115-
116-
if (reprocessingOptions.DefaultTransactionOpenMode == default
117-
&& reprocessingOptions.DefaultExecuteStrategy == default) {
118-
// that means instance is default. probably invalid
119-
reprocessingConfiguration = null;
120-
return false;
121-
}
106+
ArgumentValidator.EnsureArgumentNotNull(configurationRoot, nameof(configurationRoot));
122107

123-
var result = new ReprocessingConfiguration();
124-
if (reprocessingOptions.DefaultTransactionOpenMode != default
125-
&& Enum.TryParse<TransactionOpenMode>(reprocessingOptions.DefaultTransactionOpenMode, out var enumValue)) {
126-
result.DefaultTransactionOpenMode = enumValue;
127-
}
128-
if (!string.IsNullOrEmpty(reprocessingOptions.DefaultExecuteStrategy)) {
129-
var type = Type.GetType(reprocessingOptions.DefaultExecuteStrategy, false);
130-
if (type == null)
131-
throw new InvalidOperationException($"Can't resolve type '{reprocessingOptions.DefaultExecuteStrategy}'. Note that DefaultExecuteStrategy value should be in form of Assembly Qualified Name");
132-
result.DefaultExecuteStrategy = type;
133-
}
134-
reprocessingConfiguration = result;
135-
return true;
108+
return new ReprocessingConfigurationReader().Read(configurationRoot, sectionName ?? ConfigurationSection.DefaultSectionName);
136109
}
137110

138111
/// <summary>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using System;
2+
using Microsoft.Extensions.Configuration;
3+
using Xtensive.Orm.Configuration;
4+
5+
namespace Xtensive.Orm.Reprocessing.Configuration
6+
{
7+
internal sealed class ReprocessingConfigurationReader : IConfigurationSectionReader<ReprocessingConfiguration>
8+
{
9+
// intermediate class for reading section
10+
private class ReprocessingOptions
11+
{
12+
public TransactionOpenMode DefaultTransactionOpenMode { get; set; }
13+
14+
public string DefaultExecuteStrategy { get; set; }
15+
}
16+
17+
public ReprocessingConfiguration Read(IConfigurationSection configurationSection) => ReadInternal(configurationSection);
18+
19+
public ReprocessingConfiguration Read(IConfigurationSection configurationSection, string nameOfConfiguration) =>
20+
throw new NotSupportedException();
21+
22+
public ReprocessingConfiguration Read(IConfigurationRoot configurationRoot) =>
23+
Read(configurationRoot, ConfigurationSection.DefaultSectionName);
24+
25+
public ReprocessingConfiguration Read(IConfigurationRoot configurationRoot, string sectionName)
26+
{
27+
var section = configurationRoot.GetSection(sectionName);
28+
return ReadInternal(section);
29+
}
30+
31+
public ReprocessingConfiguration Read(IConfigurationRoot configurationRoot, string sectionName, string nameOfConfiguration) =>
32+
throw new NotSupportedException();
33+
34+
private ReprocessingConfiguration ReadInternal(IConfigurationSection section)
35+
{
36+
var reprocessingOptions = section.Get<ReprocessingOptions>();
37+
38+
if (reprocessingOptions == default) {
39+
return new ReprocessingConfiguration();
40+
}
41+
42+
if (reprocessingOptions.DefaultTransactionOpenMode == default
43+
&& reprocessingOptions.DefaultExecuteStrategy == default) {
44+
// that means instance is default. probably invalid
45+
return new ReprocessingConfiguration();
46+
}
47+
48+
var result = new ReprocessingConfiguration();
49+
if (reprocessingOptions.DefaultTransactionOpenMode != default) {
50+
result.DefaultTransactionOpenMode = reprocessingOptions.DefaultTransactionOpenMode;
51+
}
52+
if (!string.IsNullOrEmpty(reprocessingOptions.DefaultExecuteStrategy)) {
53+
var type = Type.GetType(reprocessingOptions.DefaultExecuteStrategy, false);
54+
if (type == null)
55+
throw new InvalidOperationException($"Can't resolve type '{reprocessingOptions.DefaultExecuteStrategy}'. Note that DefaultExecuteStrategy value should be in form of Assembly Qualified Name");
56+
result.DefaultExecuteStrategy = type;
57+
}
58+
return result;
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)