This repository has been archived by the owner on Dec 29, 2020. It is now read-only.
/
TypeConverter.cs
179 lines (160 loc) · 6.6 KB
/
TypeConverter.cs
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// -----------------------------------------------------------------------
// <copyright file="TypeConverter.cs" company="Project Contributors">
// Copyright Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Data;
namespace MicroLite.TypeConverters
{
/// <summary>
/// A class which allows access to <see cref="ITypeConverter"/>s.
/// </summary>
public static class TypeConverter
{
private static readonly IDictionary<Type, DbType> s_dbTypeMap = new Dictionary<Type, DbType>
{
{ typeof(byte), DbType.Byte },
{ typeof(byte?), DbType.Byte },
{ typeof(sbyte), DbType.SByte },
{ typeof(sbyte?), DbType.SByte },
{ typeof(short), DbType.Int16 },
{ typeof(short?), DbType.Int16 },
{ typeof(ushort), DbType.UInt16 },
{ typeof(ushort?), DbType.UInt16 },
{ typeof(int), DbType.Int32 },
{ typeof(int?), DbType.Int32 },
{ typeof(uint), DbType.UInt32 },
{ typeof(uint?), DbType.UInt32 },
{ typeof(long), DbType.Int64 },
{ typeof(long?), DbType.Int64 },
{ typeof(ulong), DbType.UInt64 },
{ typeof(ulong?), DbType.UInt64 },
{ typeof(float), DbType.Single },
{ typeof(float?), DbType.Single },
{ typeof(decimal), DbType.Decimal },
{ typeof(decimal?), DbType.Decimal },
{ typeof(double), DbType.Double },
{ typeof(double?), DbType.Double },
{ typeof(bool), DbType.Boolean },
{ typeof(bool?), DbType.Boolean },
{ typeof(char), DbType.StringFixedLength },
{ typeof(char?), DbType.StringFixedLength },
{ typeof(string), DbType.String },
{ typeof(byte[]), DbType.Binary },
{ typeof(DateTime), DbType.DateTime2 },
{ typeof(DateTime?), DbType.DateTime2 },
{ typeof(DateTimeOffset), DbType.DateTimeOffset },
{ typeof(DateTimeOffset?), DbType.DateTimeOffset },
{ typeof(Guid), DbType.Guid },
{ typeof(Guid?), DbType.Guid },
};
/// <summary>
/// Gets the type converter collection which contains all type converters registered with the MicroLite ORM framework.
/// </summary>
public static TypeConverterCollection Converters { get; } = new TypeConverterCollection();
/// <summary>
/// Gets the default type converter which can be used if there is no specific type converter for a given type.
/// </summary>
public static ITypeConverter Default { get; } = new ObjectTypeConverter();
/// <summary>
/// Gets the <see cref="ITypeConverter"/> for the specified type.
/// </summary>
/// <param name="type">The type to get the converter for.</param>
/// <returns>The <see cref="ITypeConverter"/> for the specified type, or null if no specific type converter exists for the type.</returns>
/// <remarks>
/// If For returns null, the TypeConverter.Default can be used.
/// </remarks>
public static ITypeConverter For(Type type)
{
for (int i = 0; i < Converters.Count; i++)
{
ITypeConverter typeConverter = Converters[i];
if (typeConverter.CanConvert(type))
{
return typeConverter;
}
}
return null;
}
/// <summary>
/// Determines whether the type is not an entity type and is a convertible type.
/// </summary>
/// <param name="type">The type to test.</param>
/// <returns>
/// true if the type is not an entity and can be converted.
/// </returns>
/// <exception cref="System.ArgumentNullException">Thrown if type is null.</exception>
public static bool IsNotEntityAndConvertible(Type type)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
if (type.IsValueType || type == typeof(string))
{
return true;
}
return For(type) != null;
}
/// <summary>
/// Registers the type mapping between a Type and DbType.
/// </summary>
/// <param name="type">The Type to be mapped.</param>
/// <param name="dbType">The DbType to be mapped to.</param>
public static void RegisterTypeMapping(Type type, DbType dbType)
=> s_dbTypeMap[type] = dbType;
/// <summary>
/// Resolves the actual type.
/// </summary>
/// <param name="type">The type to resolve.</param>
/// <returns>
/// The actual type (e.g. the inner type if it is a nullable value).
/// </returns>
/// <exception cref="System.ArgumentNullException">Thrown if type is null.</exception>
public static Type ResolveActualType(Type type)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
Type actualType = type;
if (type.IsGenericType && typeof(Nullable<>).IsAssignableFrom(type.GetGenericTypeDefinition()))
{
actualType = Nullable.GetUnderlyingType(type);
}
return actualType;
}
/// <summary>
/// Resolves the DbType mapped to the Type.
/// </summary>
/// <param name="type">The Type to resolve the DbType from.</param>
/// <returns>The DbType the Type maps to.</returns>
/// <exception cref="System.NotSupportedException">Thrown if the Type is not mapped to a DbType.</exception>
public static DbType ResolveDbType(Type type)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
Type actualType = ResolveActualType(type);
if (actualType?.IsEnum == true)
{
actualType = Enum.GetUnderlyingType(actualType);
}
if (s_dbTypeMap.TryGetValue(actualType, out DbType dbType))
{
return dbType;
}
throw new NotSupportedException(type.FullName);
}
}
}