forked from npgsql/npgsql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNullableHandler.cs
More file actions
70 lines (57 loc) · 4.19 KB
/
NullableHandler.cs
File metadata and controls
70 lines (57 loc) · 4.19 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
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Npgsql.BackendMessages;
// ReSharper disable StaticMemberInGenericType
namespace Npgsql.TypeHandling
{
delegate T ReadDelegate<T>(NpgsqlTypeHandler handler, NpgsqlReadBuffer buffer, int columnLength, FieldDescription? fieldDescription = null);
delegate ValueTask<T> ReadAsyncDelegate<T>(NpgsqlTypeHandler handler, NpgsqlReadBuffer buffer, int columnLen, bool async, FieldDescription? fieldDescription = null);
delegate int ValidateAndGetLengthDelegate<T>(NpgsqlTypeHandler handler, T value, ref NpgsqlLengthCache? lengthCache, NpgsqlParameter? parameter);
delegate Task WriteAsyncDelegate<T>(NpgsqlTypeHandler handler, T value, NpgsqlWriteBuffer buffer, NpgsqlLengthCache? lengthCache, NpgsqlParameter? parameter, bool async, CancellationToken cancellationToken = default);
static class NullableHandler<T>
{
public static readonly Type? UnderlyingType;
[NotNull] public static readonly ReadDelegate<T>? Read;
[NotNull] public static readonly ReadAsyncDelegate<T>? ReadAsync;
[NotNull] public static readonly ValidateAndGetLengthDelegate<T>? ValidateAndGetLength;
[NotNull] public static readonly WriteAsyncDelegate<T>? WriteAsync;
public static bool Exists => UnderlyingType != null;
static NullableHandler()
{
UnderlyingType = Nullable.GetUnderlyingType(typeof(T));
if (UnderlyingType == null)
return;
Read = NullableHandler.CreateDelegate<ReadDelegate<T>>(UnderlyingType, NullableHandler.ReadMethod);
ReadAsync = NullableHandler.CreateDelegate<ReadAsyncDelegate<T>>(UnderlyingType, NullableHandler.ReadAsyncMethod);
ValidateAndGetLength = NullableHandler.CreateDelegate<ValidateAndGetLengthDelegate<T>>(UnderlyingType, NullableHandler.ValidateMethod);
WriteAsync = NullableHandler.CreateDelegate<WriteAsyncDelegate<T>>(UnderlyingType, NullableHandler.WriteAsyncMethod);
}
}
static class NullableHandler
{
internal static readonly MethodInfo ReadMethod = new ReadDelegate<int?>(Read<int>).Method.GetGenericMethodDefinition();
internal static readonly MethodInfo ReadAsyncMethod = new ReadAsyncDelegate<int?>(ReadAsync<int>).Method.GetGenericMethodDefinition();
internal static readonly MethodInfo ValidateMethod = new ValidateAndGetLengthDelegate<int?>(ValidateAndGetLength).Method.GetGenericMethodDefinition();
internal static readonly MethodInfo WriteAsyncMethod = new WriteAsyncDelegate<int?>(WriteAsync).Method.GetGenericMethodDefinition();
static T? Read<T>(NpgsqlTypeHandler handler, NpgsqlReadBuffer buffer, int columnLength, FieldDescription? fieldDescription)
where T : struct
=> handler.Read<T>(buffer, columnLength, fieldDescription);
static async ValueTask<T?> ReadAsync<T>(NpgsqlTypeHandler handler, NpgsqlReadBuffer buffer, int columnLength, bool async, FieldDescription? fieldDescription)
where T : struct
=> await handler.Read<T>(buffer, columnLength, async, fieldDescription);
static int ValidateAndGetLength<T>(NpgsqlTypeHandler handler, T? value, ref NpgsqlLengthCache? lengthCache, NpgsqlParameter? parameter)
where T : struct
=> value.HasValue ? handler.ValidateAndGetLength(value.Value, ref lengthCache, parameter) : 0;
static Task WriteAsync<T>(NpgsqlTypeHandler handler, T? value, NpgsqlWriteBuffer buffer, NpgsqlLengthCache? lengthCache, NpgsqlParameter? parameter, bool async, CancellationToken cancellationToken = default)
where T : struct
=> value.HasValue
? handler.WriteWithLengthInternal(value.Value, buffer, lengthCache, parameter, async, cancellationToken)
: handler.WriteWithLengthInternal(DBNull.Value, buffer, lengthCache, parameter, async, cancellationToken);
internal static TDelegate CreateDelegate<TDelegate>(Type underlyingType, MethodInfo method)
where TDelegate : Delegate
=> (TDelegate)method.MakeGenericMethod(underlyingType).CreateDelegate(typeof(TDelegate));
}
}