【问题标题】:Creating a new instance of a class outside constructor with Dependency Injection使用依赖注入在构造函数外部创建类的新实例
【发布时间】:2024-01-08 21:45:01
【问题描述】:

我正在尝试一个示例应用程序来测试依赖注入。在使用 DI 之前,我的课堂上有以下方法:

public IQueryable<BookDTO> GetBooks()
{
    var books = from b in db.Books
                select new BookDTO()
                {
                    Id = b.Id,
                    Title = b.Title,
                    AuthorName = b.Author.Name
                };

    return books;
}

BookDTO 是在另一个项目中定义的数据传输对象。现在我想将我的项目松散地耦合在一起。所以我创建了 IDTOBase 接口并让 BookDTO 实现了这个。我有一个统一容器,我已将 BookDTO 类的相关注册到 IDTOBase。

但是我将如何在我原来的方法中重写 LINQ 查询呢?什么会代替“new BookDTO()”?

谢谢

【问题讨论】:

  • DI的目的不是松散耦合数据,而是松散耦合逻辑层。

标签: c# linq dependency-injection unity-container data-transfer-objects


【解决方案1】:

你从我认为的部分答案开始:'BookDTO 是一个数据传输对象'。因此,抽象它没有什么价值,因为它属于应用程序的一个非常特定的层。

BookDTO 的作用是作为一本书的纯数据表示(以某种可能的可序列化形式)。这将发生在您的应用程序堆栈的低级别。任何需要使用此类数据的代码都应该创建一个可以在代码中使用的域对象“Book”。这将书籍数据 (BookDTO) 的持久性和检索与其域表示 (Book) 分离。

我不认为您的接口定义有此目的,因此 DI 在这里没有目的。我觉得 DI 在这里发挥作用的地方是 Book DTO 的检索。加载书籍数据的类将注入这样的服务并使用它来检索 BookDTO 实例。

【讨论】:

  • 我对你的最后一段有点困惑。我的 EntityFramwork 存储 Book 实体。但业务逻辑使用 BookDTO。所以我有 ServiceLayer,它具有 GetBooks() 函数,该函数检索 Book 对象并将其映射到 BookDTO。在这种情况下,DI应该在哪里实施?如果我理解您的回答,那么 ServiceLayer 不应该使用任何 DI,但我的业务层可以使用 DI 来抽象 ServiceLayer 类。我的业务逻辑应该直接引用 BookDTO 吗?
  • 是的,您的业务层将使用 DI 来抽象服务层。通过这种方式,您可以针对已知的模拟/存根行为以受控方式测试业务层组件。您的业​​务层应将 BookDTO 映射到业务层表示“Book”,以便两者可以独立更改,否则您将层耦合在一起。查看 AutoMapper 以支持层之间的映射对象:automapper.org
【解决方案2】:

好吧,任何实例化对象的人都需要知道创建它的实际类型。

看起来您需要的是某种存储库,它知道IDTOBaseBookDTO。您的应用程序会知道IDTOBase。您的应用程序会发出类似BookRepo.GetBooks 的调用,其中您的存储库签名看起来像IQueryable&lt;IDTOBase&gt; GetBooks

【讨论】:

    【解决方案3】:

    您需要另一个可以为您解决依赖关系的类。

    在 DI 的大多数情况下,您会说 “给我一个 '类' 并将它具有的任何映射接口解析到它的映射类实例”,您需要的是那个“类”。

    我在学习 DI 时喜欢其中的一些示例。 http://www.asp.net/web-api/overview/advanced/dependency-injection

    【讨论】: