Skip to content

Commit

Permalink
show initial type-handler design in line with DapperLib/Dapper#1924
Browse files Browse the repository at this point in the history
  • Loading branch information
mgravell committed Jun 20, 2023
1 parent 4a088a7 commit 74557eb
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
15 changes: 15 additions & 0 deletions src/Dapper.AOT/CommandFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,21 @@ protected static object AsValue<T>(T? value) where T : struct
protected static object AsValue(object? value)
=> value ?? DBNull.Value;


/// <summary>
/// Wrap a value for use in an ADO.NET parameter
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static object AsGenericValue<T>(T value)
{
// note JIT elide here
if (typeof(T) == typeof(bool)) return AsValue(Unsafe.As<T, bool>(ref value));
if (typeof(T) == typeof(bool?)) return AsValue(Unsafe.As<T, bool?>(ref value));
if (typeof(T) == typeof(int)) return AsValue(Unsafe.As<T, int>(ref value));
if (typeof(T) == typeof(int?)) return AsValue(Unsafe.As<T, int?>(ref value));
return AsValue((object?)value);
}

/// <summary>
/// Flexibly parse an <see cref="object"/> as a value of type <typeparamref name="T"/>.
/// </summary>
Expand Down
34 changes: 34 additions & 0 deletions src/Dapper.AOT/TypeHandlerT.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Dapper.Internal;
using System;
using System.ComponentModel;
using System.Data.Common;

namespace Dapper;

/// <summary>
/// Specify that <typeparamref name="TTypeHandler"/> should be used as a custom type-handler
/// when processing values of type <typeparamref name="TValue"/>
/// </summary>
[ImmutableObject(true)]
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
public sealed class TypeHandlerAttribute<TValue, TTypeHandler> : Attribute
where TTypeHandler : TypeHandler<TValue>, new()
{}

/// <summary>
/// Process a parameter value of type <typeparamref name="T"/>
/// </summary>
public abstract class TypeHandler<T>
{
/// <summary>
/// Configure and assign a value for a parameter
/// </summary>
public virtual void SetValue(DbParameter parameter, T value)
=> parameter.Value = CommandFactory.AsGenericValue<T>(value);

/// <summary>
/// Interpret the output value from a parameter
/// </summary>
public virtual T Parse(DbParameter parameter)
=> CommandUtils.As<T>(parameter.Value);
}

0 comments on commit 74557eb

Please sign in to comment.