项目

本文档有多个版本。请选择最适合您的选项。

UI
Database

Web 应用程序开发教程(使用 ABP Suite)- 第五部分:自定义生成的代码

到目前为止,您已经为书店应用程序创建了全部功能,而无需编写任何一行代码。在这一部分中,让我们编写一些代码,并体验 ABP Suite 的一大特色功能:可自定义的代码支持

可自定义的代码支持

ABP Suite 允许您自定义生成的代码块,并在下一次 CRUD 页面生成时保留您的自定义代码更改。它提供了钩子点(hook points),供您添加自定义代码块。之后,您在这些钩子点编写的代码将会被保留,并且在后续的 CRUD 页面生成中不会被覆盖。

要启用自定义代码支持,您需要在 CRUD 页面生成 页面中勾选 可自定义的代码 选项(该选项默认已勾选),并且您已经为两个实体都启用了该功能:

自定义代码钩子点

当您启用 自定义代码支持 后,ABP Suite 会添加一些钩子点,您可以在此编写自己的自定义代码,而无需担心下一次进行 CRUD 页面生成时您的代码会被覆盖。

在 C# 方面,ABP Suite 为实体、应用服务、接口、领域服务等添加了抽象基类(以及接口的部分类)。

您可以在这些类(以 *.Extended.cs 为扩展名)中编写您的自定义代码。下次当您需要重新生成实体时,您的自定义代码不会被覆盖(只有基抽象类会被重新生成,您在 Suite 上所做的更改会得到保留):

例如,您可以像上面的例子那样创建一个新的仓储方法,在下一次 CRUD 页面生成时,ABP Suite 不会覆盖您的自定义代码。

在 UI 方面,对于 MVC、Blazor 和 Angular UI,ABP Suite 在页面内提供了方便的注释占位符。这些注释区域作为钩子点,供您添加自定义代码。

例如,如果您在 IDE 中打开 Books/Index.cshtml 文件,您会看到如下所示的占位符:

<!-- 为简洁起见省略了部分代码 -->

@section styles
{
@*//<suite-custom-code-block-1>*@
@*//</suite-custom-code-block-1>*@
}

<!-- ... -->

您可以在 占位符之间编写您的自定义代码,您还可以通过自定义 ABP Suite 模板 来扩展这些占位符。

更多信息,请参阅 自定义生成的代码文档

实现自定义代码

让我们通过实际操作来看看自定义代码支持。我们可以用一个简单的例子来演示此功能。

假设我们想要显示作者的名字及其缩写。例如,对于作者 John Ronald Reuel Tolkien,我们想要显示 John Ronald Reuel Tolkien (a.k.a J.R.R.T)。实现这一点非常简单。

我们只需要打开 src/Acme.BookStore.Application/Books/BooksAppService.Extended.cs 文件并重写基类的 GetListAsync 方法,该方法会在书籍页面被调用:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Caching;

namespace Acme.BookStore.Books
{
    public class BooksAppService : BooksAppServiceBase, IBooksAppService
    {
        //<suite-custom-code-autogenerated>
        public BooksAppService(IBookRepository bookRepository, BookManager bookManager, IDistributedCache<BookDownloadTokenCacheItem, string> downloadTokenCache, IRepository<Acme.BookStore.Authors.Author, Guid> authorRepository)
            : base(bookRepository, bookManager, downloadTokenCache, authorRepository)
        {
        }
        //</suite-custom-code-autogenerated>

        //编写您的自定义代码...
        public override async Task<PagedResultDto<BookWithNavigationPropertiesDto>> GetListAsync(GetBooksInput input)
        {
            var result = await base.GetListAsync(input);

            foreach (var book in result.Items)
            {
                var akaName = book.Author.Name.Split(" ").Select(q => q[0]).JoinAsString(".");
                book.Author.Name += $" (a.k.a {akaName})";
            }
            
            return result;
        }
    }
}
  • 这里,我们重写了 GetListAsync 方法,并根据我们的需求修改了其结果。
  • 请注意,此类继承自 BooksAppServiceBase 类,并实现了 IBooksAppService 接口。
  • 因此,ABP Suite 只会修改 BooksAppServiceBase 类,并在每次生成时实现必要的服务,但不会生成带有 *.Extended 后缀的文件,而是让您实现自己的自定义代码。
  • 您可以创建新方法、重写现有方法并改变其行为、添加自定义钩子点以扩展自定义能力等等...

现在,我们可以打开 ABP Suite 并尝试重新生成书籍实体,看看我们的自定义代码是否还在:

重新生成完成后,我们可以检查 BooksAppService.Extended.cs 文件,应该会看到我们的自定义代码仍然存在,没有任何修改。ABP Suite 没有覆盖我们的自定义代码。最后,我们可以运行应用程序来查看最终结果:

ABP Suite 的自定义代码支持不仅限于后端。您也可以自定义 UI。更多详细信息,请参阅 自定义生成的代码文档

总结

在本教程中,您使用 ABP Suite 创建了书店应用程序,而无需编写任何一行代码。然后,在这最后一部分中,您在指定的钩子点编写了自定义代码,并且这些代码没有被 ABP Suite 覆盖。


在本文档中