Skip to content

Commit b9dae91

Browse files
committed
+ Connection string parser/formatter class (based on DbConnectionStringBuilder)
+ string.ToXxx extension methods * improve targeting for ReflectionExtensions
1 parent 80ee81f commit b9dae91

File tree

9 files changed

+590
-43
lines changed

9 files changed

+590
-43
lines changed

CodeJam.Blocks.Tests/CodeJam.Blocks.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
</PropertyGroup>
1414

1515
<!-- #region Targeting -->
16-
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">
16+
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' OR '$(TargetFramework)' == 'net35' ">
1717
<Reference Include="System.ComponentModel.DataAnnotations" />
1818
</ItemGroup>
1919
<ItemGroup Condition=" '$(TargetFramework)' != 'net20' AND '$(TargetFramework)' != 'netcoreapp1.1' ">

CodeJam.Main.Tests/CodeJam.Main.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
</PropertyGroup>
1515

1616
<!-- #region Targeting -->
17-
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">
17+
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' OR '$(TargetFramework)' == 'net35' ">
1818
<Reference Include="System.ComponentModel.DataAnnotations" />
1919
</ItemGroup>
2020
<ItemGroup Condition=" '$(TargetFramework)' != 'net20' AND '$(TargetFramework)' != 'netcoreapp1.1' ">
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
using System;
2+
using System.ComponentModel;
3+
using System.ComponentModel.DataAnnotations;
4+
using System.Diagnostics.CodeAnalysis;
5+
6+
using NUnit.Framework;
7+
8+
using static NUnit.Framework.Assert;
9+
10+
namespace CodeJam.ConnectionStrings
11+
{
12+
[SuppressMessage("ReSharper", "ObjectCreationAsStatement")]
13+
public class ConnectionStringTests
14+
{
15+
private static readonly DateTimeOffset _defaultDateTimeOffset = new DateTimeOffset(2010, 11, 12, 0, 0, 0, TimeSpan.Zero);
16+
17+
public class BaseConnectionString : ConnectionStringBase
18+
{
19+
public BaseConnectionString(string connectionString) : base(connectionString) { }
20+
21+
#if NET35_OR_GREATER || TARGETS_NETCOREAPP
22+
[Required]
23+
#endif
24+
public string RequiredValue
25+
{
26+
get => TryGetValue(nameof(RequiredValue));
27+
set => SetValue(nameof(RequiredValue), value);
28+
}
29+
30+
public bool BooleanValue
31+
{
32+
get => TryGetBooleanValue(nameof(BooleanValue));
33+
set => SetValue(nameof(BooleanValue), value);
34+
}
35+
36+
public int? Int32Value
37+
{
38+
get => TryGetInt32Value(nameof(Int32Value));
39+
set => SetValue(nameof(Int32Value), value);
40+
}
41+
}
42+
43+
public class DerivedConnectionString : BaseConnectionString
44+
{
45+
public DerivedConnectionString(string connectionString) : base(connectionString) { }
46+
47+
public new string RequiredValue
48+
{
49+
get => TryGetValue(nameof(RequiredValue));
50+
set => SetValue(nameof(RequiredValue), value);
51+
}
52+
53+
public DateTimeOffset? DateTimeOffsetValue
54+
{
55+
get => TryGetDateTimeOffsetValue(nameof(DateTimeOffsetValue));
56+
set => SetValue(nameof(DateTimeOffsetValue), value);
57+
}
58+
}
59+
60+
public class NonBrowsableConnectionString : BaseConnectionString
61+
{
62+
public NonBrowsableConnectionString(string connectionString) : base(connectionString) { }
63+
64+
[Browsable(false)]
65+
public new string RequiredValue
66+
{
67+
get => TryGetValue(nameof(RequiredValue));
68+
set => SetValue(nameof(RequiredValue), value);
69+
}
70+
}
71+
72+
[Test]
73+
public void TestConnectionStringValidation()
74+
{
75+
DoesNotThrow(() => new BaseConnectionString(null));
76+
DoesNotThrow(() => new BaseConnectionString(""));
77+
DoesNotThrow(() => new BaseConnectionString("requiredValue=aaa"));
78+
DoesNotThrow(() => new BaseConnectionString("RequiredValue=aaa;IgnoredValue=123"));
79+
DoesNotThrow(() => new BaseConnectionString("") { ConnectionString = null });
80+
DoesNotThrow(() => new BaseConnectionString("") { ConnectionString = "" });
81+
DoesNotThrow(() => new BaseConnectionString("") { ConnectionString = "requiredValue=aaa" });
82+
DoesNotThrow(() => new BaseConnectionString("") { ConnectionString = "RequiredValue=aaa;IgnoredValue=123" });
83+
84+
#if NET35_OR_GREATER || TARGETS_NETCOREAPP
85+
var ex = Throws<ArgumentException>(() => new BaseConnectionString("IgnoredValue=123"));
86+
That(ex.Message, Does.Contain(nameof(BaseConnectionString.RequiredValue)));
87+
ex = Throws<ArgumentException>(
88+
() => new BaseConnectionString("")
89+
{
90+
ConnectionString = "IgnoredValue = 123"
91+
});
92+
That(ex.Message, Does.Contain(nameof(BaseConnectionString.RequiredValue)));
93+
#else
94+
DoesNotThrow(() => new BaseConnectionString("IgnoredValue=123"));
95+
DoesNotThrow(
96+
() => new BaseConnectionString("")
97+
{
98+
ConnectionString = "IgnoredValue = 123"
99+
});;
100+
#endif
101+
}
102+
103+
[Test]
104+
public void TestConnectionStringValidationOverride()
105+
{
106+
DoesNotThrow(() => new DerivedConnectionString("IgnoredValue=123"));
107+
DoesNotThrow(
108+
() => new DerivedConnectionString("")
109+
{
110+
ConnectionString = "IgnoredValue=123"
111+
});
112+
}
113+
114+
[Test]
115+
public void TestGetProperties()
116+
{
117+
var x = new BaseConnectionString("requiredValue=aaa");
118+
AreEqual(x.RequiredValue, "aaa");
119+
AreEqual(x.BooleanValue, false);
120+
AreEqual(x.Int32Value, null);
121+
122+
IsTrue(x.ContainsKey(nameof(x.RequiredValue)));
123+
IsTrue(x.TryGetValue(nameof(x.RequiredValue), out _));
124+
AreEqual(x[nameof(x.RequiredValue)], "aaa");
125+
126+
x = new BaseConnectionString("requiredValue='aa; a'");
127+
AreEqual(x.RequiredValue, "aa; a");
128+
129+
x = new BaseConnectionString("requiredValue=\"aa; a\"");
130+
AreEqual(x.RequiredValue, "aa; a");
131+
132+
// test for input string format
133+
x = new BaseConnectionString(@"
134+
RequiredValue=""aaa"" ;
135+
BooleanValue=true;
136+
Int32Value = 112");
137+
AreEqual(x.RequiredValue, "aaa");
138+
AreEqual(x.BooleanValue, true);
139+
AreEqual(x.Int32Value, 112);
140+
}
141+
142+
[Test]
143+
public void TestGetPropertiesDerived()
144+
{
145+
var x = new DerivedConnectionString("IgnoredValue=aaa");
146+
AreEqual(x.RequiredValue, null);
147+
AreEqual(x.BooleanValue, false);
148+
AreEqual(x.Int32Value, null);
149+
AreEqual(x.DateTimeOffsetValue, null);
150+
151+
x = new DerivedConnectionString("DateTimeOffsetValue=2010-11-12Z");
152+
AreEqual(x.DateTimeOffsetValue, _defaultDateTimeOffset);
153+
}
154+
155+
[Test]
156+
public void TestPropertiesRoundtrip()
157+
{
158+
var x = new DerivedConnectionString("")
159+
{
160+
RequiredValue = "A; B=C'\"",
161+
BooleanValue = true,
162+
Int32Value = -1024,
163+
DateTimeOffsetValue = _defaultDateTimeOffset
164+
};
165+
166+
var s = x.ToString();
167+
AreEqual(s, @"RequiredValue=""A; B=C'"""""";DateTimeOffsetValue=""11/12/2010 00:00:00 +00:00"";BooleanValue=True;Int32Value=-1024");
168+
169+
var x2 = new DerivedConnectionString(s);
170+
AreEqual(x2.RequiredValue, x.RequiredValue);
171+
AreEqual(x2.BooleanValue, x.BooleanValue);
172+
AreEqual(x2.Int32Value, x.Int32Value);
173+
AreEqual(x2.DateTimeOffsetValue, x.DateTimeOffsetValue);
174+
AreEqual(s, x2.ToString());
175+
}
176+
177+
[Test]
178+
public void TestIgnoredProperties()
179+
{
180+
var x = new DerivedConnectionString("");
181+
IsFalse(x.ContainsKey("IgnoredValue"));
182+
IsFalse(x.TryGetValue("IgnoredValue", out var ignored));
183+
IsNull(ignored);
184+
var ex = Throws<ArgumentException>(() => x["IgnoredValue"].ToString());
185+
That(ex.Message, Does.Contain("IgnoredValue"));
186+
187+
x = new DerivedConnectionString("IgnoredValue=123");
188+
IsFalse(x.ContainsKey("IgnoredValue"));
189+
IsFalse(x.TryGetValue("IgnoredValue", out ignored));
190+
IsNull(ignored);
191+
ex = Throws<ArgumentException>(() => x["IgnoredValue"].ToString());
192+
That(ex.Message, Does.Contain("IgnoredValue"));
193+
}
194+
195+
[Test]
196+
public void TestNonBrowsableProperties()
197+
{
198+
var x = new NonBrowsableConnectionString("")
199+
{
200+
RequiredValue = "A",
201+
BooleanValue = true,
202+
Int32Value = -1024
203+
};
204+
205+
var s = x.GetBrowsableConnectionString(true);
206+
AreEqual(s, @"RequiredValue=...;BooleanValue=True;Int32Value=-1024");
207+
208+
var x2 = new NonBrowsableConnectionString(s);
209+
AreEqual(x2.RequiredValue, "...");
210+
AreEqual(x2.BooleanValue, x.BooleanValue);
211+
AreEqual(x2.Int32Value, x.Int32Value);
212+
AreEqual(s, x2.ToString());
213+
214+
s = x.GetBrowsableConnectionString(false);
215+
AreEqual(s, @"BooleanValue=True;Int32Value=-1024");
216+
217+
x2 = new NonBrowsableConnectionString(s);
218+
AreEqual(x2.RequiredValue, null);
219+
AreEqual(x2.BooleanValue, x.BooleanValue);
220+
AreEqual(x2.Int32Value, x.Int32Value);
221+
AreEqual(s, x2.ToString());
222+
}
223+
}
224+
}

CodeJam.Main/CodeJam.Main.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
<PackageReference Include="Theraot.Core" Version="3.1.2" />
6969
</ItemGroup>
7070
<ItemGroup Condition=" '$(TargetFramework)' == 'net35' ">
71+
<Reference Include="System.ComponentModel.DataAnnotations" />
7172
<PackageReference Include="Theraot.Core" Version="3.1.2" />
7273
</ItemGroup>
7374
<ItemGroup Condition=" '$(TargetFramework)' == 'net20' ">
@@ -82,6 +83,8 @@
8283
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.5' ">
8384
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
8485
<PackageReference Include="System.ComponentModel.EventBasedAsync" Version="4.3.0" />
86+
<PackageReference Include="System.ComponentModel.Primitives" Version="4.3.0" />
87+
<PackageReference Include="System.Data.Common" Version="4.3.0" />
8588
<PackageReference Include="System.Diagnostics.TraceSource" Version="4.3.0" />
8689
<PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
8790
<PackageReference Include="System.Linq.Queryable" Version="4.3.0" />
@@ -93,6 +96,8 @@
9396
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
9497
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
9598
<PackageReference Include="System.ComponentModel.EventBasedAsync" Version="4.3.0" />
99+
<PackageReference Include="System.ComponentModel.Primitives" Version="4.3.0" />
100+
<PackageReference Include="System.Data.Common" Version="4.3.0" />
96101
<PackageReference Include="System.Diagnostics.TraceSource" Version="4.3.0" />
97102
<PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
98103
<PackageReference Include="System.Linq.Queryable" Version="4.3.0" />
@@ -110,6 +115,8 @@
110115
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">
111116
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
112117
<PackageReference Include="System.ComponentModel.EventBasedAsync" Version="4.3.0" />
118+
<PackageReference Include="System.ComponentModel.Primitives" Version="4.3.0" />
119+
<PackageReference Include="System.Data.Common" Version="4.3.0" />
113120
<PackageReference Include="System.Diagnostics.TraceSource" Version="4.3.0" />
114121
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
115122
<PackageReference Include="Theraot.Core" Version="3.1.2" />

0 commit comments

Comments
 (0)