如何在Castle Windsor for C#中解决运行时依赖项

阿杰·苏沃卡(Ajay Suwalka)

在这里,我有一个特定的场景,我需要根据用户传递连接字符串,因为可能会根据用户的企业将用户映射到不同的数据库。

这是我使用静态变量解析依赖关系的代码:

public void Install(IWindsorContainer container, IConfigurationStore store)
{
    container.Register(
        Component.For<IUserRepository>()
                 .ImplementedBy(typeof(IKS.Dare.Optimix.Repository.EntityFramework.UserModule.UserRepository))
                 .DependsOn(Dependency.OnValue("connectionString", DatabaseSettings.DefaultConnectionString))
    );
}

因为这DefaultConnectionString应该是动态的,所以我不想锁定此变量以使其成为线程安全的,因为这会降低性能。我想要一种方法来应对这种情况。

可能的考虑因素可能是我们可以举行一个会议,该会议可以如下应用:

DynamicParameters((k, d) => d["connectionString"] = Session["connectionString"])

但这是在另一个不使用任何Web组件的项目中,它只是一个安装程序项目,该项目基本上是专门为解决依赖关系而设计的。

我的通用存储库如下所示

public class GenericRepository<T> : IGenericRepository<T> where T : BaseEntity
{
        private const string IsActive = "IsActive", DbContext = "dbContext", EntityPropertyName = "Entity";

        private string connectionString = String.Empty, provider = String.Empty;

        public GenericRepository(string connectionString, string provider)
        {
            this.connectionString = connectionString;
            this.provider = provider;
        }
        public int Count()
        {
            string tableName = typeof(T).Name;
            string query = SqlQueryConstants.SelectCount + SqlQueryConstants.Space + tableName;
            int count = DbHelper.ExecuteScalar<int>(query: query, commandType: System.Data.CommandType.Text, connectionString: connectionString, provider: provider, parameters: null);
            return count;
        }
}

DBHelper类如下所示

public static int ExecuteNonQuery(string query, CommandType commandType = CommandType.StoredProcedure,
            IList<DbParameter> parameters = null, int? timeout = null, string connectionString = "", string provider = "")
        {
            using (var connection = CreateDbConnection(connectionString, provider))
            {
                connection.Open();
                using (DbCommand command = CreateDbCommand(sqlQuery: query, parameters: parameters,
                                                connection: connection, commandType: commandType, timeout: timeout))
                {
                    return command.ExecuteNonQuery();
                }
            }
        }

        public static DbParameter CreateParameter<TValue>(string name, TValue value, DbType dbType,
            ParameterDirection parameterDirection = ParameterDirection.Input, string provider = "")
        {
            DbParameter param = CreateDbProviderFactory(provider).CreateParameter();
            param.Value = value;
            param.ParameterName = name;
            param.DbType = dbType;
            param.Direction = parameterDirection;
            return param;
        }


        public static DbConnection CreateDbConnection()
        {
            return CreateDbConnection(String.Empty, String.Empty);
        }

        public static DbConnection CreateDbConnection(string connectionString = "", string provider = "")
        {
            DbConnection connection = null;
            if (String.IsNullOrEmpty(provider))
            {
                if (String.IsNullOrEmpty(DatabaseSettings.DefaultProvider))
                    throw new ArgumentNullException("provider");
                else
                    provider = DatabaseSettings.DefaultProvider;
            }
            connection = CreateDbProviderFactory(provider).CreateConnection();
            connection.ConnectionString = connectionString;
            return connection;
        }

任何帮助将不胜感激。

注意:我无法编辑史蒂文的答案。[编辑]为了更加清楚,可以将其实现为:

这里的控制器继承自BaseController

public class UserController : BaseController
    {
        //
        // GET: /Index/
        private IUserRepository userRepository;

        public UserController(IUserRepository userRepository)
            : base(userRepository)
        {
            this.userRepository = userRepository;
        }
}

而BaseController则是从Controller继承的,在Base Controller的构造函数中已在数据库中设置了设置,因此我们无需在任何地方进行设置

public abstract class BaseController : Controller
    {
        public BaseController(IUserRepository userRepository)
        {
            userRepository.connectionStringProvider.Provider = WebUtilities.CurrentUserData.Provider;
            userRepository.connectionStringProvider.ConnectionString = WebUtilities.CurrentUserData.ConnectionString;
        }
    }
史蒂文

由于连接字符串是运行时数据,因此不应使用它来构造您的应用程序组件,如本文所述因此,如本文所建议,您应该将连接字符串隐藏在提供程序抽象的后面。例如:

public interface IConnectionStringProvider {
    string ConnectionString { get; }
}

这样,您的存储库就可以依赖IConnectionStringProvider并可以IConnectionStringProvider.ConnectionString在运行时调用

public int Count()
{
    string tableName = typeof(T).Name;
    string query = SqlQueryConstants.SelectCount + SqlQueryConstants.Space + tableName;
    return DbHelper.ExecuteScalar<int>(
        this.connectionStringProvider.ConnectionString, 
        provider: provider, parameters: null);
}

创建一个IConnectionStringProviderto将为您获取正确的连接字符串将很简单

class DatabaseConnectionStringProvider : IConnectionStringProvider
{
    public string ConnectionString => Session["connectionString"];
}

由于此分类取决于特定于应用程序的内容(在这种情况下为ASP.NET会话),因此该类不应成为应用程序核心逻辑的一部分。相反,此适配器应位于应用程序的启动路径(即合成根,即配置容器的位置)中。

您甚至可能要考虑不要将传递IConnectionStringProvider到存储库中,而是创建一个将创建连接本身的抽象。这将掩盖一个事实,即完全有一个连接字符串。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在nuget库中管理Castle Windsor依赖项

如何在Castle Windsor中配置此ClientBase类

如何在Castle Windsor中不使用BasedOn方法批量注册接口?

如何在asp.net Web API中使用Castle Windsor在身份验证筛选器属性中实现依赖项注入?

Castle Windsor Interceptors - 在 ctor 中获取目标

使用Castle Windsor在WebAPI中进行依赖注入

使用Castle Windsor解决具有通用类型约束的接口

Castle Windsor-获取要解决的根组件类型

使用 Castle Windsor 在 QueryBus 中查找查询处理程序

是否可以覆盖Castle Windsor 3中的命名注册?

NServiceBus处理程序集与Castle Windsor一起命名为依赖项

如何在Castle Windsor中注册Ef核心数据库上下文?

如何在Eclipse中解决循环项目依赖性。有什么办法只能使其中一个依赖项运行时吗?

如何在SBT中将依赖项设置为运行时(以模仿Maven中的运行时作用域)?

如何自动向Castle Windsor注册开放的通用接口?

如何使Castle Windsor TraceLoggerFactory输出到Visual Studio输出窗口?

如何在运行时动态更改依赖项

如何在运行时控制OSGi中的依赖项注入

如何在gradle jar任务生成的jar中包括运行时依赖项

如何在C#中检查运行时类型

Castle Windsor 注册:无法创建组件“X.YService”,因为它具有要满足的依赖项

使用 xml/app.config 在 Castle Windsor 中添加字符串列表

Castle Windsor Ms Adapter Core 2.0的实现

Log4Net with castle windsor

Castle.Windsor CollectionResolver和组件订购

在 Castle.windsor 中注册窗体

如何在ASP.net Core 2中使用Windsor IoC

如何根据Spring Boot运行时环境在Gradle中删除依赖项?

如何在Inno Setup安装程序中捆绑来自NuGet软件包的仅运行时依赖项?