对包装类进行泛型调用

时间:2018-06-10 14:42:44

标签: c# dapper

我有这个静态类:

namespace Dapper
{
    public static class SqlMapper
    {
        public static T ExecuteScalar<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
          CommandDefinition command = new CommandDefinition(sql, param, transaction, commandTimeout, commandType, CommandFlags.Buffered, new CancellationToken());
          return SqlMapper.ExecuteScalarImpl<T>(cnn, ref command);
        }

        public static Task<int> ExecuteAsync(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
          return cnn.ExecuteAsync(new CommandDefinition(sql, param, transaction, commandTimeout, commandType, CommandFlags.Buffered, new CancellationToken()));
        }

      //...
      //Goes on for another 200 different static functions
    }
}

我想创建一个包装类,它将保存commandTimeout的默认值。我不希望它作为全局参数,我希望使用此值在bootstrapper中构建此类:

using Dapper;

public class SqlWrapper : ISqlWrapper
{
    private readonly ILogger _logger;
    private readonly int _commandTimeoutInSec;

    public SqlWrapper(ILogger logger, int commandTimeoutInSec)
    {
        _logger = logger;
        _commandTimeoutInSec = commandTimeoutInSec;
    }

    public async ExecuteScalarAsync<T>(IDbConnection cnn, string sql, object param = null,
         int? commandTimeout = null, CommandType? commandType = null)
    {
        try
        {
            using (var conn = new SqlConnection(cnn))
            {
                var commandGuid =
                    await conn.ExecuteScalarAsync<T>(sql, param, CommandType: CommandType, commandTimeout: commandTimeout ?? _commandTimeoutInSec);
                return commandGuid;
            }
        }
        catch (Exception ex)
        {
            _logger.WriteError(
                $"Job execute failed with error:", ex);
            throw;
        }
    }

    public async int ExecuteAsync(IDbConnection cnn, string sql, object param = null, int? commandTimeout = null, CommandType? commandType = null)
    {
        try
        {
            using (var conn = new SqlConnection(cnn))
            {
                var commandGuid =
                    await
                        conn.ExecuteAsync(sql, param, CommandType: CommandType,
                            commandTimeout: commandTimeout ?? _commandTimeoutInSec);
                return commandGuid;
            }
        }
        catch (Exception ex)
        {
            _logger.WriteError(
                $"Job execute failed with error:", ex);
            throw;
        }
    }

    //...
    //Goes on for the rest 200 different static functions in SqlMapper
}

问题是,我觉得实现200个函数的包装来传递默认参数是愚蠢的,有没有办法接收函数的名称作为参数的模板然后将调用传递给在SqlMapper中使用相同的名称?

1 个答案:

答案 0 :(得分:1)

您可以将以下技术应用于您的方案。想象一下,我们有这个静态类:

public static class Printer
{
    public static void Print(string output, int numberOfTimes)
    {
        for (int i = 0; i < numberOfTimes; i++)
        {
            Console.WriteLine(output);
        }
    }

    public static void Show(string output, int numberOfTimes)
    {
        for (int i = 0; i < numberOfTimes; i++)
        {
            Console.WriteLine(output);
        }
    }
}

让我们假设我们想给numberOfTimes一个默认值,然后我们可以这样做:

public class DefaultPrinter
{
    private int defaultTimes = 10;
    public void ExecuteMethod(Action<string, int> action, string output)
    {
        action(output, defaultTimes);
    }
}

现在用户不必指出打印应该发生多少次,因为上面的类将默认执行10次。

<强>用法

var printer = new DefaultPrinter();
printer.ExecuteMethod((a, b) => Printer.Print(a, b), "One");
printer.ExecuteMethod((a, b) => Printer.Show(a, b), "Two");