[英]Problem Registering a Generic Repository with Windsor IoC
我对IoC还是很陌生,也许我对泛型和继承的理解不足以实现我想要做的事情。 您可能会发现这很混乱。 我有一个通用的Repository <TEntity>基类:
public class Repository<TEntity> where TEntity : class, IEntity
{
private Table<TEntity> EntityTable;
private string _connectionString;
private string _userName;
public string UserName
{
get { return _userName; }
set { _userName = value; }
}
public Repository() {}
public Repository(string connectionString)
{
_connectionString = connectionString;
EntityTable = (new DataContext(connectionString)).GetTable<TEntity>();
}
public Repository(string connectionString, string userName)
{
_connectionString = connectionString;
_userName = userName;
EntityTable = (new DataContext(connectionString)).GetTable<TEntity>();
}
// Data access methods ...
... }
和一个继承存储库的SqlClientRepository:
public class SqlClientRepository : Repository<Client>
{
private Table<Client> ClientTable;
private string _connectionString;
private string _userName;
public SqlClientRepository() {}
public SqlClientRepository(string connectionString) : base(connectionString)
{
_connectionString = connectionString;
ClientTable = (new DataContext(connectionString)).GetTable<Client>();
}
public SqlClientRepository(string connectionString, string userName)
: base(connectionString, userName)
{
_connectionString = connectionString;
_userName = userName;
ClientTable = (new DataContext(connectionString)).GetTable<Client>();
}
// data access methods unique to Client repository
... }
Repository类提供了一些通用方法,例如Save <TEntity>,Delete <TEntity>等,我希望所有我的存储库派生类都可以共享。
TEntity参数限于IEntity接口:
public interface IEntity
{
int Id { get; set; }
NameValueCollection GetSaveRuleViolations();
NameValueCollection GetDeleteRuleViolations();
}
这允许Repository类在其Save和Delete方法中引用这些方法。 单元测试可以在模拟SqlClientRepository实例上正常运行,也可以在真实数据库上正常运行单元测试。 但是,在MVC上下文中:
public class ClientController : Controller
{
private SqlClientRepository _clientRepository;
public ClientController(SqlClientRepository clientRepository)
{
this._clientRepository = clientRepository;
}
public ClientController() { }
// ViewResult methods ...
... }
..._ clientRepository始终为null 。 我正在使用Windor Castle作为IoC容器。 配置如下:
<component id="ClientRepository" service="DomainModel.Concrete.Repository`1[[DomainModel.Entities.Client, DomainModel]], DomainModel"
type="DomainModel.Concrete.SqlClientRepository, DomainModel" lifestyle="PerWebRequest">
<parameters>
<connectionString>#{myConnStr}</connectionString>
</parameters>
</component>
我在Windsor配置文件中尝试了许多变体。 我怀疑这更多是上述代码中的设计缺陷。 在查看代码时,我发现在向IoC容器注册组件时,服务可能始终是接口。 这可能吗? 有人有建议吗? 提前致谢。
----修订----
作为对答案1的回应,我添加了一个新的代码示例,因为在下面的注释部分中该格式无法正确格式化。
我可以使它工作:
public class ClientController : Controller
{
private IClientRepository _clientRepository;
public ClientController(IClientRepository clientRepository) { ... }
}
public interface IClientRepository : IRepository<Client> { ... }
public class SqlClientRepository : IClientRepository { ... }
...但是现在我需要在SqlClientRepository中复制我的Save和Delete方法,并且我的通用Repository类的好处也丢失了。 一旦我尝试让SqlClientRepository再次从Repository <Client>继承,如下所示:
public class SqlClientRepository : Repository<Client>, IClientRepository { ... }
...我的_clientRepository控制器中的空值返回。 有什么办法可以做到吗? 我觉得我尝试了许多变体,但做对了。
再次感谢你的帮助。
不,服务通常不必是接口。 服务是组件向外界公开的东西( 请参阅doco ,让我知道是否有意义)。
因此,您的ClientController
构造函数说“我依赖SqlClientRepository
服务 ”,这很不好(因为服务应该是抽象的(最好是接口)),但这并不重要。
您正在注册的组件 (名为ClientRepository),正在注册为Repository<Client>
service 。
希望到目前为止,您已经看到了问题所在。 ClientComponent
需要SqlClientRepository
,但是您已注册的组件不会将自身显示为SqlClientRepository
,而是显示为Repository<Client>
,因此Windsor认为: “好吧,因为我没有SqlClientRepository
服务 ,所以我将使用其他构造函数来创建ClientController
” ( 请参阅doco以获取有关Windsor如何选择要使用的构造函数的说明)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.