forked from npgsql/npgsql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEnumHandler.cs
More file actions
96 lines (83 loc) · 3.46 KB
/
EnumHandler.cs
File metadata and controls
96 lines (83 loc) · 3.46 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
using Npgsql.BackendMessages;
using NpgsqlTypes;
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Reflection;
using System.Text;
namespace Npgsql.TypeHandlers
{
internal interface IEnumHandler { }
internal class EnumHandler<TEnum> : TypeHandler<TEnum>, IEnumHandler,
ISimpleTypeReader<TEnum>, ISimpleTypeWriter
where TEnum : struct
{
readonly Dictionary<TEnum, string> _enumToLabel;
readonly Dictionary<string, TEnum> _labelToEnum;
public EnumHandler()
{
Contract.Requires(typeof(TEnum).GetTypeInfo().IsEnum, "EnumHandler instantiated for non-enum type");
// Reflect on our enum type to find any explicit mappings
if (!typeof(TEnum).GetFields(BindingFlags.Static | BindingFlags.Public).Any(t => t.GetCustomAttributes(typeof(EnumLabelAttribute), false).Any())) {
return;
}
_enumToLabel = new Dictionary<TEnum, string>();
_labelToEnum = new Dictionary<string, TEnum>();
foreach (var field in typeof(TEnum).GetFields(BindingFlags.Static | BindingFlags.Public))
{
var attribute = (EnumLabelAttribute)field.GetCustomAttributes(typeof(EnumLabelAttribute), false).FirstOrDefault();
var enumName = attribute == null ? field.Name : attribute.Label;
var enumValue = (Enum)field.GetValue(null);
_enumToLabel[(TEnum)(object)enumValue] = enumName;
_labelToEnum[enumName] = (TEnum)(object)enumValue;
}
}
public TEnum Read(NpgsqlBuffer buf, int len, FieldDescription fieldDescription)
{
var str = buf.ReadString(len);
TEnum value;
var success = _labelToEnum == null
? Enum.TryParse(str, out value)
: _labelToEnum.TryGetValue(str, out value);
if (!success)
throw new SafeReadException(new InvalidCastException(String.Format("Received enum value '{0}' from database which wasn't found on enum {1}", str, typeof(TEnum))));
return value;
}
public int ValidateAndGetLength(object value, NpgsqlParameter parameter)
{
if (!(value is TEnum))
throw CreateConversionException(value.GetType());
string str;
if (_enumToLabel == null)
{
str = value.ToString();
}
else
{
var asEnum = (TEnum)value;
if (!_enumToLabel.TryGetValue(asEnum, out str)) {
throw new InvalidCastException(String.Format("Can't write value {0} as enum {1}", asEnum, typeof(TEnum)));
}
}
return Encoding.UTF8.GetByteCount(str);
}
public void Write(object value, NpgsqlBuffer buf, NpgsqlParameter parameter)
{
string str;
if (_enumToLabel == null) {
str = value.ToString();
} else {
var asEnum = (TEnum)value;
if (!_enumToLabel.TryGetValue(asEnum, out str)) {
throw new InvalidCastException(String.Format("Can't write value {0} as enum {1}", asEnum, typeof(TEnum)));
}
}
buf.WriteString(str);
}
internal EnumHandler<TEnum> Clone()
{
return new EnumHandler<TEnum>();
}
}
}