Skip to content

Commit 904cee2

Browse files
committed
...
1 parent 6f40199 commit 904cee2

File tree

4 files changed

+234
-14
lines changed

4 files changed

+234
-14
lines changed

src/Options/FluiTec.AppFx.Options/ConfigurationExtension.cs

+16-13
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using System.Reflection;
55
using Microsoft.Extensions.Configuration;
6+
using Microsoft.Extensions.Logging;
67

78
namespace FluiTec.AppFx.Options
89
{
@@ -25,26 +26,28 @@ private static string NameByType(Type entityType)
2526
return ConfigurationNames[entityType];
2627
}
2728

28-
/// <summary> An IConfigurationRoot extension method that gets a configuration. </summary>
29-
/// <typeparam name="TSettings"> Type of the settings. </typeparam>
30-
/// <param name="configuration"> The configuration to act on. </param>
31-
/// <param name="configurationKey"> The configuration key. </param>
32-
/// <returns> The configuration. </returns>
29+
/// <summary>An IConfigurationRoot extension method that gets a configuration.</summary>
30+
/// <typeparam name="TSettings"> Type of the settings. </typeparam>
31+
/// <param name="configuration"> The configuration to act on. </param>
32+
/// <param name="configurationKey"> The configuration key. </param>
33+
/// <param name="loggerFactory"> (Optional) The logger factory. </param>
34+
/// <returns>The configuration.</returns>
3335
public static TSettings GetConfiguration<TSettings>(this IConfigurationRoot configuration,
34-
string configurationKey)
36+
string configurationKey, ILoggerFactory loggerFactory = null)
3537
where TSettings : new()
3638
{
37-
return new ConfigurationSettingsService<TSettings>(configuration, configurationKey).Get();
39+
return new ConfigurationSettingsService<TSettings>(configuration, configurationKey, loggerFactory).Get();
3840
}
3941

40-
/// <summary> An IConfigurationRoot extension method that gets a configuration. </summary>
41-
/// <typeparam name="TSettings"> Type of the settings. </typeparam>
42-
/// <param name="configuration"> The configuration to act on. </param>
43-
/// <returns> The configuration. </returns>
44-
public static TSettings GetConfiguration<TSettings>(this IConfigurationRoot configuration)
42+
/// <summary>An IConfigurationRoot extension method that gets a configuration.</summary>
43+
/// <typeparam name="TSettings"> Type of the settings. </typeparam>
44+
/// <param name="configuration"> The configuration to act on. </param>
45+
/// <param name="loggerFactory"> (Optional) The logger factory. </param>
46+
/// <returns>The configuration.</returns>
47+
public static TSettings GetConfiguration<TSettings>(this IConfigurationRoot configuration, ILoggerFactory loggerFactory = null)
4548
where TSettings : new()
4649
{
47-
return new ConfigurationSettingsService<TSettings>(configuration, NameByType(typeof(TSettings))).Get();
50+
return new ConfigurationSettingsService<TSettings>(configuration, NameByType(typeof(TSettings)), loggerFactory).Get();
4851
}
4952
}
5053
}

src/Options/FluiTec.AppFx.Options/ConfigurationSettingsService.cs

+22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
2+
using System.Runtime.CompilerServices;
23
using Microsoft.Extensions.Configuration;
4+
using Microsoft.Extensions.Logging;
35

46
namespace FluiTec.AppFx.Options
57
{
@@ -14,6 +16,9 @@ public class ConfigurationSettingsService<TSettings> : ISettingsService<TSetting
1416
/// <summary> The configuration key. </summary>
1517
protected readonly string ConfigurationKey;
1618

19+
/// <summary>The logger.</summary>
20+
private readonly ILogger _logger;
21+
1722
/// <summary> Options for controlling the operation. </summary>
1823
protected TSettings Settings;
1924

@@ -28,19 +33,36 @@ public ConfigurationSettingsService(IConfiguration configuration, string configK
2833
Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
2934
}
3035

36+
/// <summary>Constructor.</summary>
37+
/// <param name="configuration"> The configuration. </param>
38+
/// <param name="configKey"> The configuration key. </param>
39+
/// <param name="loggerFactory"> The logger factory. </param>
40+
public ConfigurationSettingsService(IConfiguration configuration, string configKey,
41+
ILoggerFactory loggerFactory) : this(configuration, configKey)
42+
{
43+
if (loggerFactory != null)
44+
{
45+
_logger = loggerFactory.CreateLogger(GetType());
46+
}
47+
}
48+
3149
/// <summary> Gets the get. </summary>
3250
/// <returns> The TSettings. </returns>
3351
public TSettings Get()
3452
{
3553
if (Settings != null)
3654
return Settings;
3755

56+
_logger?.LogDebug($"Loading Configuration for \"{typeof(TSettings).Name}\" by Key \"{ConfigurationKey}\".");
57+
3858
// load config-section
3959
var section = Configuration.GetSection(ConfigurationKey);
4060

4161
// parse config-section
4262
Settings = section.Get<TSettings>();
4363

64+
_logger.LogDebug($"Parsed Configuration for \"{typeof(TSettings).Name}\", Content: {ObjectDumper.Dump(Settings)}");
65+
4466
return Settings;
4567
}
4668
}

src/Options/FluiTec.AppFx.Options/FluiTec.AppFx.Options.csproj

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@
1010
<PostBuildEvent></PostBuildEvent>
1111
<PreBuildEvent></PreBuildEvent>
1212
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
13-
<Version>1.0.7</Version>
13+
<Version>1.0.8</Version>
1414
</PropertyGroup>
1515

1616
<ItemGroup>
1717
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.1" />
1818
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.0.1" />
19+
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.1.0" />
1920
</ItemGroup>
2021

2122
<Target Name="NugetTarget" AfterTargets="Build" Condition="'$(ConfigurationName)'=='Release'">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
// source: https://stackoverflow.com/questions/852181/c-printing-all-properties-of-an-object
2+
3+
using System;
4+
using System.Collections;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Reflection;
8+
using System.Text;
9+
10+
namespace FluiTec.AppFx.Options
11+
{
12+
/// <summary>An object dumper.</summary>
13+
public class ObjectDumper
14+
{
15+
#region Fields
16+
17+
/// <summary>The level.</summary>
18+
private int _level;
19+
20+
/// <summary>Size of the indent.</summary>
21+
private readonly int _indentSize;
22+
23+
/// <summary>The string builder.</summary>
24+
private readonly StringBuilder _stringBuilder;
25+
26+
/// <summary>The hash list of found elements.</summary>
27+
private readonly List<int> _hashListOfFoundElements;
28+
29+
#endregion
30+
31+
#region Constructors
32+
33+
/// <summary>Constructor.</summary>
34+
/// <param name="indentSize"> Size of the indent. </param>
35+
private ObjectDumper(int indentSize)
36+
{
37+
_indentSize = indentSize;
38+
_stringBuilder = new StringBuilder();
39+
_hashListOfFoundElements = new List<int>();
40+
}
41+
42+
#endregion
43+
44+
/// <summary>Dumps the given element.</summary>
45+
/// <param name="element"> The element to dump. </param>
46+
/// <returns>A string.</returns>
47+
public static string Dump(object element)
48+
{
49+
return Dump(element, 2);
50+
}
51+
52+
/// <summary>Dumps the given element.</summary>
53+
/// <param name="element"> The element to dump. </param>
54+
/// <param name="indentSize"> Size of the indent. </param>
55+
/// <returns>A string.</returns>
56+
public static string Dump(object element, int indentSize)
57+
{
58+
var instance = new ObjectDumper(indentSize);
59+
return instance.DumpElement(element);
60+
}
61+
62+
/// <summary>Dumps an element.</summary>
63+
/// <param name="element"> The element to dump. </param>
64+
/// <returns>A string.</returns>
65+
private string DumpElement(object element)
66+
{
67+
if (element == null || element is ValueType || element is string)
68+
{
69+
Write(FormatValue(element));
70+
}
71+
else
72+
{
73+
var objectType = element.GetType();
74+
if (!typeof(IEnumerable).IsAssignableFrom(objectType))
75+
{
76+
Write("{{{0}}}", objectType.FullName);
77+
_hashListOfFoundElements.Add(element.GetHashCode());
78+
_level++;
79+
}
80+
81+
if (element is IEnumerable enumerableElement)
82+
{
83+
foreach (var item in enumerableElement)
84+
{
85+
if (item is IEnumerable && !(item is string))
86+
{
87+
_level++;
88+
DumpElement(item);
89+
_level--;
90+
}
91+
else
92+
{
93+
if (!AlreadyTouched(item))
94+
DumpElement(item);
95+
else
96+
Write("{{{0}}} <-- bidirectional reference found", item.GetType().FullName);
97+
}
98+
}
99+
}
100+
else
101+
{
102+
var members = element.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance);
103+
foreach (var memberInfo in members)
104+
{
105+
var fieldInfo = memberInfo as FieldInfo;
106+
var propertyInfo = memberInfo as PropertyInfo;
107+
108+
if (fieldInfo == null && propertyInfo == null)
109+
continue;
110+
111+
var type = fieldInfo != null ? fieldInfo.FieldType : propertyInfo.PropertyType;
112+
var value = fieldInfo != null
113+
? fieldInfo.GetValue(element)
114+
: propertyInfo.GetValue(element, null);
115+
116+
if (type.IsValueType || type == typeof(string))
117+
{
118+
Write("{0}: {1}", memberInfo.Name, FormatValue(value));
119+
}
120+
else
121+
{
122+
var isEnumerable = typeof(IEnumerable).IsAssignableFrom(type);
123+
Write("{0}: {1}", memberInfo.Name, isEnumerable ? "..." : "{ }");
124+
125+
var alreadyTouched = !isEnumerable && AlreadyTouched(value);
126+
_level++;
127+
if (!alreadyTouched)
128+
DumpElement(value);
129+
else
130+
Write("{{{0}}} <-- bidirectional reference found", value.GetType().FullName);
131+
_level--;
132+
}
133+
}
134+
}
135+
136+
if (!typeof(IEnumerable).IsAssignableFrom(objectType))
137+
{
138+
_level--;
139+
}
140+
}
141+
142+
return _stringBuilder.ToString();
143+
}
144+
145+
/// <summary>Already touched.</summary>
146+
/// <param name="value"> The value. </param>
147+
/// <returns>True if it succeeds, false if it fails.</returns>
148+
private bool AlreadyTouched(object value)
149+
{
150+
if (value == null)
151+
return false;
152+
153+
var hash = value.GetHashCode();
154+
return _hashListOfFoundElements.Any(t => t == hash);
155+
}
156+
157+
/// <summary>Writes.</summary>
158+
/// <param name="value"> The value. </param>
159+
/// <param name="args"> A variable-length parameters list containing arguments. </param>
160+
private void Write(string value, params object[] args)
161+
{
162+
var space = new string(' ', _level * _indentSize);
163+
164+
if (args != null)
165+
value = string.Format(value, args);
166+
167+
_stringBuilder.AppendLine(space + value);
168+
}
169+
170+
/// <summary>Format value.</summary>
171+
/// <param name="o"> An object to process. </param>
172+
/// <returns>The formatted value.</returns>
173+
private static string FormatValue(object o)
174+
{
175+
switch (o)
176+
{
177+
case null:
178+
return "null";
179+
case DateTime _:
180+
return ((DateTime)o).ToShortDateString();
181+
case string _:
182+
return $"\"{o}\"";
183+
case char _ when (char)o == '\0':
184+
return string.Empty;
185+
case ValueType _:
186+
return o.ToString();
187+
case IEnumerable _:
188+
return "...";
189+
}
190+
191+
return "{ }";
192+
}
193+
}
194+
}

0 commit comments

Comments
 (0)