温莎城堡控制反转 (IoC):使用 Web.config 解决依赖关系

发布于 2024-10-19 04:05:19 字数 3150 浏览 2 评论 0原文

我正在根据 相关问题。我想使用 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.Config 数据库名称查找连接字符串:

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
}

对此有任何帮助吗?

PS

即使我使用硬编码的数据库名称(如 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 来存储温莎城堡的特定部分。

I was exploring the installer functionality of Castle Windsor based on the answers from a related question. I want to use the Web.config to specify the name of the database and I would rather not explicitly set the database name in my code. I tried Krzysztof Koźmic's example and when I debut the project my break-point at container.Register gets hit, but the dependency is still not resolved:

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 suggests that we can use the Web.config to resolve dependencies (note that he's doing this to get the connection string, but my connection string is encrypted so I'm doing in in a slightly different way):

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

My SqlUsersRepository and IUsersRepository are in the same namespace, but they're part of a class library which gets referenced in the current project. SqlUsersRepository looks up the connection string from the Web.Config the database name:

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
}

Any help on this?

P.S.

I'm still getting an exception, even if I use the hard-coded database name (as seen in the RepositoriesInstaller):

Server Error in '/' Application. Can't
create component
'MyProjectName.Controllers.UserController'
as it has dependencies to be
satisfied.
MyProjectName.Controllers.UserController
is waiting for the following
dependencies:

Services:
- MyProjectName.Entities.IUsersRepository
which was not registered. Description:
An unhandled exception occurred during
the execution of the current web
request. Please review the stack trace
for more information about the error
and where it originated in the code.

Exception Details:
Castle.MicroKernel.Handlers.HandlerException:
Can't create component
'MyProjectName.Controllers.UserController'
as it has dependencies to be
satisfied.
MyProjectName.Controllers.UserController
is waiting for the following
dependencies:

Services:
- MyProjectName.Entities.IUsersRepository
which was not registered.

Update
I've posted an answer which addresses the exception problem, but I'm yet to figure out how to use the Web.config to store Castle Windsor specific sections.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

心房的律动 2024-10-26 04:05:19

您应该能够通过将 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 属性匹配即可。

You should be able to achieve this by reducing the XML to this:

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

and then make sure your registration registers the repository under the right key/id - e.g. like this:

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

where all keys will be set to the short name of each concrete type.

Please note that this naming scheme might not be appropriate for you, so you should probably adapt the c.Named(...) to whatever you deem right for your use case. Just make sure that the registration key for your repository matches that if the id attribute in the XML.

白鸥掠海 2024-10-26 04:05:19

DependsOn 您完成此操作的方式 = 名为“databaseName”的参数具有带有键“MyDatabaseName”的组件依赖项。

您想要执行 .Parameters(ForKey.Named("databasename").Value(ConfigurationManager.ConnectionStrings["MyDatabasename"].ConnectionString)).LifeStyle.Transient。 ...

DependsOn the way you've done it = the parameter named "databaseName" has a component dependency with a key "MyDatabaseName".

You want to do a .Parameters(ForKey.Named("databasename").Value(ConfigurationManager.ConnectionStrings["MyDatabasename"].ConnectionString)).LifeStyle.Transient. ...

南街女流氓 2024-10-26 04:05:19

我发现了依赖异常...问题是我的存储库位于不同的程序集中,因此我必须对安装进行一些操作:

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 的城堡部分获取数据库名称。不过配置。

I figured out the dependency exception... the issue was that my repositories are in a different assembly, so I had to rig the installation a bit:

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" })));
    }
}

Still trying to figure out how to get the database name from the castle section of the Web.config though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文