温莎城堡控制反转 (IoC):使用 Web.config 解决依赖关系
我正在根据 相关问题。我想使用 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>
我的 SqlUsersRepository
和 IUsersRepository
是在同一命名空间中,但它们是当前项目中引用的类库的一部分。 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您应该能够通过将 XML 简化为以下内容来实现此目的:
然后确保您的注册在正确的键/id 下注册存储库 - 例如,如下所示:
其中所有键都将设置为每个具体类型的短名称。
请注意,此命名方案可能不适合您,因此您可能应该将
c.Named(...)
调整为您认为适合您的用例的名称。只需确保存储库的注册密钥与 XML 中的id
属性匹配即可。You should be able to achieve this by reducing the XML to this:
and then make sure your registration registers the repository under the right key/id - e.g. like this:
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 theid
attribute in the XML.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. ...
我发现了依赖异常...问题是我的存储库位于不同的程序集中,因此我必须对安装进行一些操作:
仍在尝试找出如何从 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:
Still trying to figure out how to get the database name from the castle section of the Web.config though.