forked from kurrent-io/KurrentDB
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathConnectionString.cs
More file actions
110 lines (102 loc) · 4.4 KB
/
ConnectionString.cs
File metadata and controls
110 lines (102 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
namespace EventStore.ClientAPI
{
/// <summary>
/// Methods for dealing with connection strings.
/// </summary>
public class ConnectionString
{
private static readonly Dictionary<Type, Func<string, object>> translators;
static ConnectionString()
{
translators = new Dictionary<Type, Func<string, object>>()
{
{typeof(int), x => int.Parse(x)},
{typeof(decimal), x=>double.Parse(x)},
{typeof(string), x => x},
{typeof(bool), x=>bool.Parse(x)},
{typeof(long), x=>long.Parse(x)},
{typeof(byte), x=>byte.Parse(x)},
{typeof(double), x=>double.Parse(x)},
{typeof(float), x=>float.Parse(x)},
{typeof(TimeSpan), x => TimeSpan.FromMilliseconds(int.Parse(x))},
{typeof(GossipSeed[]), x => x.Split(',').Select(q =>
{
try
{
var pieces = q.Trim().Split(':');
if (pieces.Length != 2) throw new Exception("could not split ip address from port.");
return new GossipSeed(new IPEndPoint(IPAddress.Parse(pieces[0]), int.Parse(pieces[1])));
}
catch (Exception ex)
{
throw new Exception(string.Format("Gossip seed {0} is not in correct format", q), ex);
}
}).ToArray()
}
};
}
/// <summary>
/// Parses a connection string into its pieces represented as kv pairs
/// </summary>
/// <param name="connectionString">the connection string to parse</param>
/// <returns></returns>
internal static IEnumerable<KeyValuePair<string, string>> GetConnectionStringInfo(string connectionString)
{
var builder = new DbConnectionStringBuilder(false) { ConnectionString = connectionString };
//can someome mutate this builder before the enumerable is closed sure but thats the fun!
return from object key in builder.Keys
select new KeyValuePair<string, string>(key.ToString(), builder[key.ToString()].ToString());
}
/// <summary>
/// Returns a <see cref="ConnectionSettings"></see> for a given connection string.
/// </summary>
/// <param name="connectionString"></param>
/// <returns>a <see cref="ConnectionSettings"/> from the connection string</returns>
public static ConnectionSettings GetConnectionSettings(string connectionString)
{
var settings = ConnectionSettings.Default;
var items = GetConnectionStringInfo(connectionString).ToArray();
return Apply(items, settings);
}
private static string WithSpaces(string name)
{
var ret = "";
foreach (var c in name)
{
if(char.IsUpper(c))
{
ret += " ";
}
ret += c;
}
return ret.Trim();
}
private static T Apply<T>(IEnumerable<KeyValuePair<string , string>> items, T obj)
{
var fields = typeof (T).GetFields().Where(x=>x.IsPublic).Select(x => new Tuple<string, FieldInfo>(x.Name.ToLower(), x))
.Concat(typeof(T).GetFields().Where(x => x.IsPublic).Select(x => new Tuple<string, FieldInfo>(WithSpaces(x.Name).ToLower(), x)))
.GroupBy(x => x.Item1)
.ToDictionary(x => x.First().Item1.ToLower(), x=>x.First().Item2);
foreach (var item in items)
{
FieldInfo fi = null;
if (!fields.TryGetValue(item.Key, out fi)) continue;
Func<string, object> func = null;
if (!translators.TryGetValue(fi.FieldType, out func))
{
throw new Exception(string.Format("Can not map field named {0} as type {1} has no translator", item, fi.FieldType.Name));
}
fi.SetValue(obj, func(item.Value));
}
return obj;
}
}
}