【问题标题】:Castle Windsor Inversion of Control (IoC): using the Web.config to resolve dependenciesCastle Windsor Inversion of Control (IoC):使用 Web.config 解决依赖关系
【发布时间】:2011-02-26 20:59:57
【问题描述】:

我正在根据 related question 的回答探索 Castle Windsor 的安装程序功能。我想使用 Web.config 来指定数据库的名称,我宁愿不在我的代码中明确设置数据库名称。我尝试了 Krzysztof Koźmic 的示例,当我首次启动项目时,我在 container.Register 处的断点被击中,但依赖关系仍未解决:

public class RepositoriesInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(AllTypes.FromThisAssembly()
                            .Where(Component.IsInSameNamespaceAs<SqlUsersRepository>())
                            .WithService.DefaultInterface()
                            .Configure(c => c.LifeStyle.Transient
                            .DependsOn(new { databaseName = "MyDatabaseName" })));
    }
}

Sanders 建议我们可以使用 Web.config 来解决依赖关系(请注意,他这样做是为了获取连接字符串,但我的连接字符串是加密的,所以我的做法略有不同):

<castle>
    <components>
      <component id="SqlUsersRepository"
          service="MyDevArmyModel.Entities.IUsersRepository, MyDevArmyModel"
          type="MyDevArmyModel.Entities.SqlUsersRepository, MyDevArmyModel">
        <parameters>
          <databaseName>MyDatabaseName</databaseName>
        </parameters>
      </component>
    </components>
</castle>

我的SqlUsersRepositoryIUsersRepository 在同一个命名空间中,但它们是当前项目中引用的类库的一部分SqlUsersRepository从Web中查找连接字符串。配置数据库名称:

public interface IUsersRepository
{
    IQueryable<User> Users { get; }
    // ...
    // and some other things 
    // ...

}

public class SqlUsersRepository : IUsersRepository
{
    private DataContext dataContext;
    private Table<User> usersTable;

    public IQueryable<User> Users { get { return usersTable; } }

    public SqlUsersRepository(string databaseName)
    {
        HttpRequestWrapper request = new HttpRequestWrapper(System.Web.HttpContext.Current.Request);
        Configuration config = WebConfigurationManager.OpenWebConfiguration(request.ApplicationPath);
        dataContext = new DataContext(config.GetConnetionString(databaseName));
        usersTable = dataContext.GetTable<User>();
    }

    // .... the rest of the repository goes here
}

有什么帮助吗?

附言

即使我使用硬编码的数据库名称(如 RepositoriesInstaller 中所示),我仍然遇到异常:

“/”应用程序中的服务器错误。不能 创建组件 'MyProjectName.Controllers.UserController' 因为它有依赖关系 使满意。 MyProjectName.Controllers.UserController 正在等待以下 依赖:

服务: - MyProjectName.Entities.IUsersRepository 没有注册。描述: 期间发生未处理的异常 当前网络的执行 要求。请查看堆栈跟踪 有关错误的更多信息 以及它起源于代码的位置。

异常详情: Castle.MicroKernel.Handlers.HandlerException: 无法创建组件 'MyProjectName.Controllers.UserController' 因为它有依赖关系 使满意。 MyProjectName.Controllers.UserController 正在等待以下 依赖:

服务: - MyProjectName.Entities.IUsersRepository 没有注册。

更新 我已经发布了一个解决异常问题的答案,但我还没有弄清楚如何使用 Web.config 来存储温莎城堡的特定部分。

【问题讨论】:

  • 请不要将桑德斯的书用于与温莎有关的任何内容,它现在已经非常过时了。
  • @Mauricio,使用 Web.config 存储存储库类 必须 所需的连接字符串和数据库名称很有用!它允许您通过简单地在 Web.config 中添加/更改连接字符串来交换数据库...
  • 当然可以,但不是那样。这是一个过时的机制。
  • @Mauricio,我全神贯注!我今天整天都在寻找一种从温莎部分获取自定义参数的方法......你有任何参考资料或任何我可以看的东西吗?我正准备开始啃我的键盘,因为我想不通!我不确定啃我的键盘会做什么(也许会产生一些随机的字符序列,这些字符最终会成为宇宙的答案),但它会产生令人信服的效果!

标签: c# asp.net-mvc asp.net-mvc-2 inversion-of-control castle-windsor


【解决方案1】:

您应该能够通过将 XML 简化为以下方式来实现这一点:

<castle>
    <components>
      <component id="SqlUsersRepository">
        <parameters>
          <databaseName>MyDatabaseName</databaseName>
        </parameters>
      </component>
    </components>
</castle>

然后确保您的注册在正确的密钥/ID 下注册了存储库 - 例如像这样:

container.Register(AllTypes(...).Configure(c => c.Named(c.Implementation.Name)))

所有键都将设置为每个具体类型的短名称。

请注意,此命名方案可能不适合您,因此您应该将c.Named(...) 调整为您认为适合您的用例的任何名称。只需确保您的存储库的注册密钥与 XML 中的 id 属性匹配即可。

【讨论】:

  • 我仍然遇到异常:“SqlUsersRepository 正在等待以下键...键(具有特定键的组件)- 未注册的数据库名称。”所以我没有得到的部分是如何确定存储库的注册密钥(以及如何确保它与 id 属性匹配?
  • 我对“(...) waiting for the following keys (...)”错误的最佳猜测是您忘记在实例化时将XmlInterpreter 传递给Windsor,如下所示:@ 987654327@
  • 关于命名,最好在容器中明确命名存储库
【解决方案2】:

DependsOn 你的做法 = 名为“databaseName”的参数有一个带有键“MyDatabaseName”的组件依赖项。

你想做一个.Parameters(ForKey.Named("databasename").Value(ConfigurationManager.ConnectionStrings["MyDatabasename"].ConnectionString)).LifeStyle.Transient. ...

【讨论】:

  • 我想避免在程序中专门命名数据库名称...我可以在 Web.config 中有一个“自定义”条目,它告诉我数据库名称。使用 CastleWindsor,该自定义条目应该位于 Web.config 的 &lt;castle&gt;...&lt;/castle&gt; 部分,但它不起作用。我想我只需要自己阅读即可,无需依赖 CastleWindsor 来完成。
【解决方案3】:

我发现了依赖异常...问题是我的存储库位于不同的程序集中,所以我不得不稍微安装一下:

public class RepositoriesInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        foreach (AssemblyName name in Assembly.GetExecutingAssembly().GetReferencedAssemblies())
        {
            Assembly asm = Assembly.Load(name);
            container.Register(AllTypes.FromAssemblyNamed(asm.FullName)
                            .Where(Component.IsInSameNamespaceAs<SqlUsersRepository>())
                            .WithService.DefaultInterface()
                            .Configure(c => c.LifeStyle.Transient
                            .DependsOn(new { databaseName = "MyDatabaseName" })));
        }

        container.Register(AllTypes.FromThisAssembly()
                            .Where(Component.IsInSameNamespaceAs<SqlUsersRepository>())
                            .WithService.DefaultInterface()
                            .Configure(c => c.LifeStyle.Transient
                            .DependsOn(new { databaseName = "MyDatabaseName" })));
    }
}

仍在尝试弄清楚如何从 Web.config 的城堡部分获取数据库名称。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-21
    • 1970-01-01
    • 1970-01-01
    • 2012-09-08
    • 2015-11-13
    • 1970-01-01
    相关资源
    最近更新 更多