Skip to content

Commit

Permalink
SnConfig: strongly typed section association is removed. (#9)
Browse files Browse the repository at this point in the history
* Strongly typed section association is removed. SectionAttribute class deleted. Unnecessary overloads are removed.
  • Loading branch information
kavics authored and tusmester committed Mar 3, 2017
1 parent fea8799 commit 61799e8
Show file tree
Hide file tree
Showing 5 changed files with 5 additions and 410 deletions.
131 changes: 0 additions & 131 deletions src/SenseNet.Tools.Tests/SnConfigTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,8 @@

namespace SenseNet.Tools.Tests
{
#region Test helper classes

[SectionName("feature1")]
internal class SnTestConfig : SnConfig
{
}
[SectionName("")]
internal class SnTestConfigInvalid : SnConfig
{
}
internal class SnTestConfigNoAttribute : SnConfig
{
}

internal enum ConfigEnum { Value1, Value2, Value3 }

#endregion

[TestClass]
public class SnConfigTests
{
Expand Down Expand Up @@ -137,7 +121,6 @@ public void SnConfig_SectionName_NonExistingValue()
// no section, no key
Assert.IsNull(SnConfig.GetValue<string>("NO-feature", "NO-KEY"));
Assert.IsNull(SnConfig.GetValue<string>((string)null, "NO-KEY"));
Assert.IsNull(SnConfig.GetValue<string>((Type)null, "NO-KEY"));

// default values
Assert.AreEqual("DEFAULT", SnConfig.GetValue("feature1", "NO-KEY", "DEFAULT"));
Expand Down Expand Up @@ -169,33 +152,6 @@ public void SnConfig_SectionName_TypeConversion()
Assert.IsTrue(a2.SequenceEqual(new[] { 7, 8, 9 }));
}
}
[TestMethod]
public void SnConfig_SectionType_TypeConversion()
{
using (InMemoryConfigProvider.Create(TestAppSettings, TestConfigSections))
{
Assert.AreEqual(456, SnConfig.GetValue<SnTestConfig, int>("key2"));
Assert.AreEqual(456, SnConfig.GetValue(typeof(SnTestConfig), "key2", 0));

Assert.AreEqual(3.4, SnConfig.GetValue<SnTestConfig, double>("key3"));
Assert.AreEqual(3.4, SnConfig.GetValue(typeof(SnTestConfig), "key3", 0.0));

Assert.AreEqual(ConfigEnum.Value2, SnConfig.GetValue<SnTestConfig, ConfigEnum>("key6"));
Assert.AreEqual(ConfigEnum.Value2, SnConfig.GetValue(typeof(SnTestConfig), "key6", ConfigEnum.Value1));

var a1 = SnConfig.GetList<SnTestConfig, string>("key4");
Assert.IsTrue(a1.SequenceEqual(new[] { "d", "e", "f" }));

a1 = SnConfig.GetList(typeof(SnTestConfig), "key4", new List<string>());
Assert.IsTrue(a1.SequenceEqual(new[] { "d", "e", "f" }));

var a2 = SnConfig.GetList<SnTestConfig, int>("key5");
Assert.IsTrue(a2.SequenceEqual(new[] { 7, 8, 9 }));

a2 = SnConfig.GetList(typeof(SnTestConfig), "key5", new List<int>());
Assert.IsTrue(a2.SequenceEqual(new[] { 7, 8, 9 }));
}
}

[TestMethod]
public void SnConfig_SectionName_Boundaries()
Expand All @@ -217,63 +173,6 @@ public void SnConfig_SectionName_Boundaries()
Assert.AreEqual(2.3, b2);
}
}
[TestMethod]
public void SnConfig_SectionType_Boundaries()
{
using (InMemoryConfigProvider.Create(TestAppSettings, TestConfigSections))
{
var b1 = SnConfig.GetInt<SnTestConfig>("key2", 0, 400);
Assert.AreEqual(456, b1);
b1 = SnConfig.GetInt<SnTestConfig>("key2", 0, 500);
Assert.AreEqual(500, b1);
b1 = SnConfig.GetInt<SnTestConfig>("key2", 0, 0, 400);
Assert.AreEqual(400, b1);

var b2 = SnConfig.GetDouble<SnTestConfig>("key3", 0, 1);
Assert.AreEqual(3.4, b2);
b2 = SnConfig.GetDouble<SnTestConfig>("key3", 0, 4.5);
Assert.AreEqual(4.5, b2);
b2 = SnConfig.GetDouble<SnTestConfig>("key3", 0, 1, 2.3);
Assert.AreEqual(2.3, b2);
}
}

[TestMethod]
public void SnConfig_SectionType_ExistingValue()
{
using (InMemoryConfigProvider.Create(TestAppSettings, TestConfigSections))
{
Assert.IsTrue(SnConfig.GetValue<SnTestConfig, bool>("key8"));
Assert.IsTrue(SnConfig.GetValue<bool>(typeof(SnTestConfig), "key8"));
Assert.IsTrue(SnConfig.GetValue(typeof(SnTestConfig), "key8", false));

Assert.AreEqual("value999", SnConfig.GetValue<SnTestConfig, string>("key1"));
Assert.AreEqual("value999", SnConfig.GetValue<string>(typeof(SnTestConfig), "key1"));
Assert.AreEqual("value999", SnConfig.GetValue(typeof(SnTestConfig), "key1", string.Empty));

Assert.AreEqual("value999", SnConfig.GetString<SnTestConfig>("key1"));
Assert.AreEqual("value999", SnConfig.GetString(typeof(SnTestConfig), "key1"));

//empty value
Assert.IsFalse(SnConfig.GetValue<SnTestConfig, bool>("key7"));
Assert.AreEqual(0, SnConfig.GetValue<SnTestConfig, int>("key7"));
Assert.AreEqual(0, SnConfig.GetValue<SnTestConfig, double>("key7"));
}
}
[TestMethod]
public void SnConfig_SectionType_NonExistingValue()
{
using (InMemoryConfigProvider.Create(TestAppSettings, TestConfigSections))
{
Assert.IsFalse(SnConfig.GetValue<SnTestConfig, bool>("NO-KEY"));
Assert.IsFalse(SnConfig.GetValue<bool>(typeof(SnTestConfig), "NO-KEY"));

Assert.AreEqual("default", SnConfig.GetValue<SnTestConfig, string>("NO-KEY", "default"));
Assert.AreEqual("default", SnConfig.GetValue(typeof(SnTestConfig), "NO-KEY", "default"));

Assert.IsTrue(SnConfig.GetListOrEmpty<SnTestConfig, string>("NO-KEY").SequenceEqual(new List<string>()));
}
}

//============================================================================== Error tests

Expand All @@ -297,35 +196,5 @@ public void SnConfig_TypeConversion_Error2()
SnConfig.GetList<int>("feature1", "key4");
}
}
[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void SnConfig_SectionType_Error1()
{
using (InMemoryConfigProvider.Create(TestAppSettings, TestConfigSections))
{
// type error
SnConfig.GetValue<int>(typeof(string), "key1");
}
}
[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void SnConfig_SectionType_Error2()
{
using (InMemoryConfigProvider.Create(TestAppSettings, TestConfigSections))
{
// type error
SnConfig.GetValue<int>(typeof(SnTestConfigInvalid), "key1");
}
}
[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void SnConfig_SectionType_Error3()
{
using (InMemoryConfigProvider.Create(TestAppSettings, TestConfigSections))
{
// type error
SnConfig.GetValue<int>(typeof(SnTestConfigNoAttribute), "key1");
}
}
}
}
14 changes: 5 additions & 9 deletions src/SenseNet.Tools/Configuration/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,18 @@ public class ExampleConfig : SnConfig
This way your properties will be initialized only once, when the runtime first touches your config class.

### Sections
When calling a loader method, you can provide the section path as the first parameter. The base class will try to load values from that section first, and if not found (or the provided section is null), only than will turn to the central appSettings section and look for the key there.
When calling a loader method, you provide the section path as the first parameter. The base class will try to load values from that section first, and if not found (or the provided section is null), only than will turn to the central appSettings section and look for the key there.

### Default values
As you can see in the example above, it is possible to provide a default value for the loader methods available in the base class. This makes it a very simple API that lets you define all the necessary information in one line when loading a config value.

### Generic section definition
It is also possible to provide the section info for loader metheds in a strongly typed way, by defining the section once in a class attribute:
## Loader methods
The loader methods published by the base *SnConfig* class give you an easy way to **load strongly typed values** from configuration files. There is a generic method for types where an automatic conversion is possible (even for *enums*), and there are other helper methods for loading arrays and specialized ones with an API for defining boundaries (e.g. min or max for *int* and *double* values).

```csharp
[SectionName("exampleapp/feature1")]
public class ExampleConfig : SnConfig
{
public static List<int> MyList { get; internal set; } = GetList<ExampleConfig, int>("MyListValue");
public static int TimeoutValue { get; internal set; } = GetInt<ExampleConfig>("TimeoutValue", 60, 10, 100);
public static string[] NetworkTargets { get; internal set; } = GetListOrEmpty<string>("exampleapp/sampleComponent", "NetworkTargets").ToArray();
public static int MyIntValue { get; internal set; } = GetInt("exampleapp/otherSection", "myIntValue", 60, 10);
}
```

## Loader methods
The loader methods published by the base *SnConfig* class give you an easy way to **load strongly typed values** from configuration files. There is a generic method for types where an automatic conversion is possible (even for *enums*), and there are other helper methods for loading arrays and specialized ones with an API for defining boundaries (e.g. for *int* or *double* values).
23 changes: 0 additions & 23 deletions src/SenseNet.Tools/Configuration/SectionNameAttribute.cs

This file was deleted.

Loading

0 comments on commit 61799e8

Please sign in to comment.