【机译】ABP Helper Methods
在编码时,我们经常使用扩展方法和辅助方法。它们帮助我们以声明的方式实现通用操作。我们使用它们将文本分成几行,按条件查询集合,从一种类型转换为另一种类型,以及用于许多其他目的……
在本文中,我想展示ABP框架定义和使用的一些有用的扩展方法。我个人在日常代码中经常使用它们,它们在许多情况下可以减少开发时间并防止重复。
以下是我们将在本文中介绍的扩展方法和帮助程序方法的列表:
Check
类(及其方法,如 NotNullOrWhiteSpace
和 Length
)
OneTimeRunner
类
AbpDictionaryExtensions
类的一些扩展方法(TryGetValue
、GetOrDefault
和 GetOrAdd
)
AbpEnumerableExtensions
类的一些扩展方法( JoinAsString
和 WhereIf
)
AbpStringExtensions
类的一些扩展方法( EnsureEndsWith
、 EnsureStartsWith
、 NormalizeLineEndings
、 RemovePostFix
、SplitToLines
和 TruncateWithPostfix
)
AbpTypeExtensions
类的一些扩展方法(IsAssignableTo
和 GetBaseClasses
)
CurrentUserExtensions
类的一些扩展方法(GetId
和 FindClaimValue
)
我的目标是使这篇文章成为实用指南,这样就不会对这些方法进行冗长的描述,相反,我将在一个句子中描述它们,然后展示一个用法示例。另外,我的目标是保持本文的更新,每当我开始使用扩展方法或帮助程序类时,我都会尝试将其添加到本文中。您还可以在下面评论您在日常代码中使用的扩展/帮助程序方法,以便我可以将它们添加到文章中。
Check 类
可以在实体的构造函数中使用 Check.NotNull
和 Check.NotNullOrWhiteSpace
方法,以确保实体的完整性,如下所示:
public class Book : AggregateRoot<Guid>
{
public string Name { get; set; }
public string Description { get; set; }
//...
public Book(Guid id, string name, string description) : base(id)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name)); //检查字符串是否为空或空白,如果是则抛出异常
Description = Check.Length(description, nameof(description), BookConsts.MaxDescriptionLength); //检查给定描述的最大长度,如果超过该长度则抛出异常
}
}
除了这两个方法之外, Check
类还提供了许多其他有用的方法,例如 Check.NotNull<>
、 Check.NotNullOrEmpty
、 AssignableTo<>
、 Range
和 Positive
。您可以看到其他方法的 Check 类。
OneTimeRunner 类
OneTimeRunner
是一个实用程序类,它保证每个应用程序只执行一次代码块,即使多次调用它也是如此。
private readonly static OneTimeRunner OneTimeRunner = new OneTimeRunner();
for(int i = 1; i < 10; i++)
{
OneTimeRunner.Run(() =>
{
Console.WriteLine("it's called: " + i + " time(s)");
});
}
//Prints: "it's called 1 time(s)"
ABP框架在很多地方都使用这个类.例如,ABP框架在模块类中使用此类来配置全局功能,如下所示:
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public override void PreConfigureServices(ServiceConfigurationContext context)
{
OneTimeRunner.Run(() =>
{
GlobalFeatureManager.Instance.Enable<PaymentFeature>();
});
}
每当需要确保代码块仅运行一次时,都可以使用此类(例如,在应用程序启动时使用此类可能很有用)
Dictionary 扩展
AbpDictionaryExtensions
类提供了有用的方法,例如 TryGetValue
、 GetOrDefault
和 GetOrAdd
。
示例:
//检查该条目是否存在于字典中
if(JobQueues.TryGetValue(jobName, our var jobQueue))
{
//在作业队列上执行操作
}
JobQueues.GetOrDefault(jobName): //如果存在则返回jobQueue,否则返回null
//尝试获取作业队列,如果找不到,则向字典中添加新项并返回。
JobQueues.GetOrAdd(
jobName,
() => new JobQueue(jobName)
);
TryGetValue
:用于尝试获取字典中的值(如果存在)。如果该值存在,则返回 true 和字典项的值。否则,返回 false 和字典项的默认值(对于引用类型为 null,对于数字值为 0,等等)。GetOrDefault
:从字典中获取具有给定键的值。如果找不到,则返回默认值。GetOrAdd
:使用给定键从字典中获取值。如果找不到值,它会根据将其作为参数提供的工厂方法创建一个新值。
Enumerable 扩展
AbpEnumerableExtensions 类提供了有用的方法,例如 JoinAsString 和 WhereIf 。此外,此类中还定义了其他扩展方法。它们在查询中使用特别有用。
示例:
//将以逗号分隔的书名连接起来
var bookNamesSeperatedWithComma = bookNames.JoinAsString(".");
//如果startTime不为空,则应用过滤器
var identitySecurityLog = securityLogs.WhereIf(
startTime.HasValue, //条件
securityLog => securityLog.CreationTime >= startTime.Value //过滤
)
.First();
JoinAsString
:连接集合的成员,在每个成员之间使用指定的分隔符。在上面的例子中,我们用它来将所有 bookNames 存储在一个string
字段中,用逗号分隔(“bookName1.bookName2.....”)。WhereIf
:如果给定条件为 true,则按给定谓词筛选列表。
String 扩展
我经常使用 AbpStringExtension
类的扩展方法。以下是其中的一些:
-
EnsureEndsWith
:如果给定字符串不以字符结尾,则在给定字符串的末尾添加一个字符。 -
EnsureStartsWith
:如果给定字符串不以字符开头,则向该字符串的开头添加字符。 -
NormalizeLineEndings
:将字符串中的行尾转换为Environment.NewLine
。 -
RemovePostFix
:从给定字符串的末尾删除给定后缀的第一个匹配项。 -
SplitToLines
:使用字符串。拆分方法将给定字符串拆分为Environment.NewLine
。 -
TruncateWithPostfix
:如果字符串超过最大长度,则从字符串的开头获取字符串的子字符串。它添加了一个“...”后缀到字符串的末尾(如果字符串被截断)。
示例:
var detailPage = url.EnsureEndsWith("/") + "Detail"; //在URL的末尾添加/detail
var urlWithHttps = url.EnsureStartsWith("https://"); //确保给定的URL以“https://”开头
//使用Environment.NewLine作为行尾,用Environment.NewLine替换\n(使其与环境无关)
var normalizedContent = fileContent.NormalizeLineEndings();
//根据给定的字符串删除后修复
var classNameWithoutManagerPostfix = nameof(MyDomainManager).RemovePostFix("Manager");
//将字符串内容拆分为行,以生成字符串数组
string[] lines = fileContent.SplitToLines();
//如果描述的长度超过247,它将截断字符串并添加后缀 (...)
var truncatedDescription = post.Description.TruncateWithPostfix(247, "...");
Type 扩展
AbpTypeExtensions
类提供有用的类型扩展,例如 GetFullNameWithAssemblyName
和 IsAssignableTo
方法。
例如,我们可以使用 GetFullNameWithAssemblyName
方法在异常消息中输出类型的程序集全名,以便于诊断错误:
throw new ArgumentException($"should be assignable to {typeof(MyBaseClass).GetFullNameWithAssemblyName()}");
另一方面, IsAssignableTo
扩展方法可用于检查类是从基类继承还是实现接口:
if(typeof(TEntity).IsAssignableTo<IHasCreationTime>())
{
//TEntity应该实现IHasCreationTime
}
它在内部使用 Type.IsAssignableFrom
方法。
Current User 扩展
您可能知道,我们可以从 ICurrentUser
或 CurrentUse
r 类中获取有关当前用户的信息。我们可以获取当前用户的 Id
,检查当前用户是否经过身份验证 (IsAuthenticated
) 等。
CurrentUser.Id
是可为空的属性。因为用户可能尚未通过身份验证。但是,有时您可能期望对当前用户进行身份验证才能查看页面并根据当前用户执行某些操作。对于这种情况,我们知道 CurrentUser.Id
不能为空。因此,我们可以通过使用 GetId
扩展方法将当前用户的 Id
作为不可为空的 Guid
类型获取:
Guid? currentUserId = CurrentUser.Id; //我们需要检查它是否为空或者不使用它
Guid currentUserId = CurrentUser.GetId();
此外,还有一些其他扩展方法(如 FindClaimValue
方法)可能很有用。例如,我们可以使用此扩展方法获取当前用户的电话号码,如下所示:
string phoneNumber = CurrentUser.FindClaimValue(AbpClaimTypes.PhoneNumber);
感谢您阅读这篇文章,下一篇见。(转:https://engincanv.github.io/abp/2023/06/10/abp-helper-methods.html)