C# · 12月 23, 2021

c# – 如何将依赖项注入到实现接口的类中?

我知道接口不能定义构造函数.强制所有实现接口的类在同一个合同中接收它们的依赖关系的最佳做法是什么.我知道可以通过属性将依赖项注入到对象中,但是通过构造函数传递它们对我来说更有意义.如何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;}

正如您所说,您还可以将依赖项实现为属性(或参数),但这将对您的依赖项进行硬编码,而不是使它们特定于实现.您将解耦您的特定会话实现,但您仍然必须依赖会话.

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 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 // …}

只有在使用某种可以为您构建/提供依赖关系的依赖注入框架时,构造函数注入才有效.即使没有框架,属性和参数注入也会起作用.

我相信这三种都是公认的做法.至少有几个流行的框架支持构造函数和属性注入.

这意味着由您决定对您的项目最有意义的决定取决于您.权衡是一种易于追踪的依赖图,与更强的耦合相比.该决定当然不必是全构造函数或全属性/参数.

要考虑的另一个更高级别的抽象是抽象工厂类.如果要对一组依赖项进行分组,或者需要在运行时构造它们的实例,则可以执行此操作:

public interface IInstallationFactory{ IUser CreateRegisteredUser(Guid userSid); IPackage CreateKNownPackage(Guid id); IInstaller CreateInstaller();}

各种框架也支持抽象工厂.