Ninject,DapperWrapper注入SqlExecutor

时间:2013-11-07 23:26:47

标签: ninject

我正在尝试创建一些“存储库”样式类,以通过DapperWrapper包装对Dapper的调用。尝试将SqlExecutor注入存储库,检查属性以确定要连接的数据库。

这是存储库实现,因此您可以看到我想要做的事情:

public class ProviderRepository : IProviderRepository<SearchType>
{
    private readonly IDbExecutor executor;

    public ProviderRepository([BHN]IDbExecutor executor)
    {
        this.executor = executor;
    }

    public IList<SearchType> GetAllSearchTypes()
    {
        return executor
            .Query<SearchType>("BHN.pSEL_LU_SEARCHTYPE_Load", commandType: CommandType.StoredProcedure)
            .ToList();
    }
}

这是我的ninject绑定,我知道这很糟糕但只是为了说明我想要做的事情:

 kernel.Bind<IDbExecutor>().To<SqlExecutor>()
                .WhenTargetHas<BHNAttribute>()
                .WithConstructorArgument("sqlConnection",
                    new SqlConnection(connections["ProviderSearch"].ConnectionString));

注意:BHNAttribute只是一个继承自Attribute的空类。

现在明显的问题是在应用程序启动时创建了sql连接,我明白了,但是如何在使用它而不是在应用程序加载时进行加载?我一直在玩Ninject Factory扩展,但是我遇到了实现可能会出现问题的问题。所以我创造了这个:

public class ExecutorFactory
{
    private ISqlExecutorFactory executor;
    public ExecutorFactory(ISqlExecutorFactory executor)
    {
        this.executor = executor;
    }

    public void Do()
    {
        var e = this.executor.CreateSqlExecutor("string");
    }
}

public interface ISqlExecutorFactory
{
    SqlExecutor CreateSqlExecutor(string conn);
}

我的绑定看起来像这样:

kernel.Bind<ISqlExecutorFactory>.ToFactory();

工厂类中的“字符串”将是“ProviderSearch”并且需要传递给我假设的ToFactory()方法,但我不明白我将如何做到这一点并结合使用BHNAttribute,就像我一样以前做过。或者,如果在这一点上甚至可能。

我是以错误的方式看待这个吗?

1 个答案:

答案 0 :(得分:1)

所以我自己想出了这个...有趣的解决方案,所以我想我会为世界分享它。我最终使用了提供程序(ToProvider)

我的提供者实施:

public class ExecutorProvider : Provider<IDbExecutor>
{
    private readonly string _connectoinString;

    public ExecutorProvider(Func<string> connectionString)
    {
        _connectionString = connectionString();
    }

    protected override IDbExecutor CreateInstance(IContext context)
    {
        return new SqlExecutor(() => {
            var sqlconnection = new SqlConnection(_connectionString);
            sqlconnection.Open();
            return sqlconnection;
        });
    }
}

然后我使用Lazy(T)创建了一个SqlExecutor的新实现,以便在使用时仅实例化并打开SqlConnection:

public class SqlExecutor : IDbExecutor
{
    readonly Lazy<SqlConnection> _sqlConnection;

    public SqlExecutor(Func<SqlConnection> sqlConnection)
    {
        _sqlConnection = new Lazy<SqlConnection>(() => sqlConnection());
    }

    public int Execute(
        string sql,
        object param = null,
        IDbTransaction transaction = null,
        int? commandTimeout = default(int?),
        CommandType? commandType = default(CommandType?))
    {
        return _sqlConnection.Value.Execute(
            sql,
            param,
            transaction,
            commandTimeout,
            commandType);
    }

    public IEnumerable<dynamic> Query(
        string sql,
        object param = null,
        IDbTransaction transaction = null,
        bool buffered = true,
        int? commandTimeout = default(int?),
        CommandType? commandType = default(CommandType?))
    {
        return _sqlConnection.Value.Query(
            sql,
            param,
            transaction,
            buffered,
            commandTimeout,
            commandType);
    }

    public IEnumerable<T> Query<T>(
        string sql,
        object param = null,
        IDbTransaction transaction = null,
        bool buffered = true,
        int? commandTimeout = default(int?),
        CommandType? commandType = default(CommandType?))
    {
        return _sqlConnection.Value.Query<T>(
            sql,
            param,
            transaction,
            buffered,
            commandTimeout,
            commandType);
    }

    public void Dispose()
    {
        _sqlConnection.Value.Dispose();
    }
}

然后是我的约束力:

kernel.Bind<IDbExecutor>().ToProvider(new ExecutorProvider(() 
        => connections["ProviderSearch"].ConnectionString))
    .WhenTargetHas<BHNAttribute>()
    .InRequestScope();

这允许我在注入我的实现类时执行此操作,以将注入的sql执行器与基于该属性的数据库连接相关联:

public class ProviderRepository : IProviderRepository
{
    private readonly IDbExecutor executor;

    public ProviderRepository([BHN]IDbExecutor executor)
    {
        this.executor = executor;
    }

    public IList<SearchType> GetAllSearchTypes()
    {
        return executor
            .Query<SearchType>("pSEL_LU_SEARCHTYPE_Load", commandType: CommandType.StoredProcedure)
            .ToList();
    }
}

BHNAttribute([BHN])只是一个继承自Attribute的空类。

注意:是的我知道使用存储过程这是蹩脚的,但遗憾的是我的双手被绑在那个上。

我不想重新创建SqlExecutor类,但这非常有用。