c# - 如何将依赖项注入(inject)实现接口(interface)的类?

标签 c# interface dependency-injection constructor

我知道接口(interface)不能定义构造函数。强制所有实现接口(interface)的类在统一契约中接收它们的依赖项的最佳实践是什么。我知道整数可以通过属性将依赖项注入(inject)对象,但通过构造函数传递它们对我来说更有意义。那怎么DI呢?

最佳答案

我知道你说过你想要一份稳定的契约(Contract)。但是提供稳定接口(interface)的一个优点是您的依赖项可能会随着不同的实现而发生巨大变化,这将减少耦合:

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

如您所说,您还可以将依赖项作为属性(或参数)来实现,但这将对您的依赖项进行硬编码,而不是使它们成为特定于实现的。您将分离您的特定 session 实现,但您仍然必须依赖于 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 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
    // ...
}

构造函数注入(inject)只有在您使用某种可以为您处理构建/提供依赖项的依赖注入(inject)框架时才有效。即使没有框架,属性和参数注入(inject)也能正常工作。

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

这意味着您可以决定什么对您的项目最有意义。权衡是一个易于追踪的依赖图,而不是更强的耦合。该决定当然也不必是全构造函数或全属性/参数。

要考虑的另一个更高级别的抽象是抽象工厂类。如果你想对一组依赖项进行分组,或者你需要在运行时构建它们的实例,你会这样做:

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

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

关于c# - 如何将依赖项注入(inject)实现接口(interface)的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4115453/

相关文章:

c# - 无法加载文件或程序集... Windows Azure 网站

c# - 需要帮助转换

Golang - [...] 接口(interface)的总和{}

Scala:通过 Reader 和兼容性进行依赖注入(inject)

java - 使用 google-guice 注入(inject)列表的最佳方法是什么?

c# - 删除除 <NIS/> 、<NONNATIVE/> 和空格之外的字符

interface - 如何自动生成已实现接口(interface)的方法

java - 编写自定义事件的监听器接口(interface)

c# - Unity的属性注入(inject)导致堆栈溢出

c# - Azure 媒体服务 Web 播放选项