Xaq*_*ron 6 c# constructor dependency-injection interface
我知道接口不能定义构造函数.强制所有实现接口的类在同一个合同中接收它们的依赖关系的最佳做法是什么.我知道可以通过属性将依赖项注入到对象中,但是通过构造函数传递它们对我来说更有意义.如何DI呢?
我知道你说你想要一份稳定的合同.但是,不提供稳定接口的一个优点是,您的依赖关系可能随着不同的实现而变化很大,这会减少耦合:
public interface IBlogRepository
{
IEnumerable<Entry> GetEntries(int pageId, int pageCount);
}
class BlogDatabase : IBlogRepository
{
public BlogDatabase(ISession session)
{
this.session = session;
}
public IEnumerable<Entry> GetEntries(int pageId, int pageCount)
{
// Not that you should implement your queries this way...
var query = session.CreateQuery("from BlogEntry");
return query.Skip(pageId * pageCount).Take(pageCount);
}
private ISession session;
}
Run Code Online (Sandbox Code Playgroud)
正如您所说,您还可以将依赖项实现为属性(或参数),但这将对您的依赖项进行硬编码,而不是使它们特定于实现.您将解耦您的特定会话实现,但您仍然必须依赖会话.
public interface IBlogRepository
{
ISession Session { get; set; }
IEnumerable<Entry> GetEntries(int pageId, int pageCount);
IEnumerable<Entry> GetEntriesWithSession(ISession session,
int pageId, int pageCount);
}
class BlogDatabase : IBlogRepository
{
public ISession Session { Get; set; }
public IEnumerable<Entry> GetEntries(int pageId, int pageCount)
{
var query = Session.CreateQuery ...
}
public IEnumerable<Entry> GetEntries(ISession session, int pageId, int pageCount)
{
var query = session.CreateQuery ...
}
}
class BlogFile : IBlogRepository
{
// ISession has to abstract a file handle. We're still okay
// ...
}
class BlogInMemory : IBlogRepository
{
// ISession abstracts nothing.
// Maybe a lock, at best, but the abstraction is still breaking down
// ...
}
Run Code Online (Sandbox Code Playgroud)
只有在使用某种可以为您构建/提供依赖关系的依赖注入框架时,构造函数注入才有效.即使没有框架,属性和参数注入也会起作用.
我相信这三种都是公认的做法.至少有几个流行的框架支持构造函数和属性注入.
这意味着由您决定对您的项目最有意义的决定取决于您.权衡是一种易于追踪的依赖图,与更强的耦合相比.该决定当然不必是全构造函数或全属性/参数.
要考虑的另一个更高级别的抽象是抽象工厂类.如果要对一组依赖项进行分组,或者需要在运行时构造它们的实例,则可以执行此操作:
public interface IInstallationFactory
{
IUser CreateRegisteredUser(Guid userSid);
IPackage CreateKnownPackage(Guid id);
IInstaller CreateInstaller();
}
Run Code Online (Sandbox Code Playgroud)
各种框架也支持抽象工厂.
我们都知道这可以通过许多不同的方法实现,但有意义的方法肯定更受欢迎。我定义了一些set-only属性,然后该对象负责保存对传递给它的内容的引用:
public interface IBlogRepository
{
ISession Session { set; }
}
class BlogRepository : IBlogRepository
{
private ISession m_session;
ISession Session
{
set { m_session = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
这样,每个实现该接口的类都知道该set-only属性是依赖注入,因为set-only很少使用属性。我不确定这个方法是否被称为 a good practice,但对我来说,从现在开始。
| 归档时间: |
|
| 查看次数: |
2460 次 |
| 最近记录: |