技术心得记录:开源项目Humanizer介绍

简介: 技术心得记录:开源项目Humanizer介绍

  Humanizer 能够满足您所有.Net关于操作和展示以下类型的需求,包括字符串、枚举、日期、时间、时间跨度、数字和数量。它采用 MIT 进行授权分发。


1、人性化字符串


人性化的字符串扩展名使您可以将原本由计算机处理的字符串转换为更具可读性的人性化字符串。 它的基础是在BDDfy框架中设置的,在该框架中,类名,方法名和属性被转换为易于阅读的句子。


"PascalCaseInputStringIsTurnedIntoSentence".Humanize() => "Pascal case input string is turned into sentence"


"Underscored_input_string_is_turned_into_sentence".Humanize() => "Underscored input string is turned into sentence"


"Underscored_input_String_is_turned_INTO_sentence".Humanize() => "Underscored input String is turned INTO sentence"


请注意,仅包含大写字母且仅包含一个单词的字符串始终被视为首字母缩写词(无论其长度如何)。 为了确保任何字符串都将始终被人性化,您必须使用转换(请参见下面的Transform方法):


// acronyms are left intact


"HTML".Humanize() => "HTML"


// any unbroken upper case string is treated as an acronym


"HUMANIZER".Humanize() => "HUMANIZER"


"HUMANIZER".Transform(To.LowerCase, To.TitleCase) => "Humanizer"


您还可以指定所需的字母大小写:


"CanReturnTitleCase".Humanize(LetterCasing.Title) => "Can Return Title Case"


"Can_return_title_Case".Humanize(LetterCasing.Title) => "Can Return Title Case"


"CanReturnLowerCase".Humanize(LetterCasing.LowerCase) => "can return lower case"


"CanHumanizeIntoUpperCase".Humanize(LetterCasing.AllCaps) => "CAN HUMANIZE INTO UPPER CASE"


LetterCasing API和接受它的方法是V0.2时代的遗留物,将来会不推荐使用。 代替的是,您可以使用下面介绍的Transform方法。


2、非人性化的字符串


就像您可以将计算机友好的字符串人性化为人类友好的字符串一样,您也可以将人类友好的字符串人性化为计算机友好的字符串:


"Pascal case input string is turned into sentence".Dehumanize() => "PascalCaseInputStringIsTurnedIntoSentence"


3、转换字符串


有一种Transform方法可以代替接受LetterCasing的LetterCasing,ApplyCase和Humanize重载。 转换方法签名如下:


string Transform(this string input, params IStringTransformer【】 transformers)


对于字母大小写,还有一些IStringTransformer的现成实现:


"Sentence casing".Transform(To.LowerCase) => "sentence casing"


"Sentence casing".Transform(To.SentenceCase) => "Sentence casing"


"Sentence casing".Transform(To.TitleCase) => "Sentence Casing"


"Sentence casing".Transform(To.UpperCase) => "SENTENCE CASING"


LowerCase是To类的公共静态属性,它返回私有ToLowerCase类的实例,该实例实现IStringTransformer并知道如何将字符串转换为小写。


与ApplyCase和LetterCasing相比,使用Transform和IStringTransformer的好处是LetterCasing是枚举,并且您只能使用框架中的内容,而IStringTransformer是可以在代码库中一次实现并与Transform方法一起使用的接口,从而可以轻松扩展 。


4、截断字符串


您可以使用Truncate方法截断字符串:


"Long text to truncate".Truncate(10) => "Long text…"


默认情况下,“ ...”字符用于截断字符串。 使用'...'字符而不是“ ...”的优点是前者仅使用一个字符,因此允许在截断之前显示更多文本。 如果需要,还可以提供自己的截断字符串:


"Long text to truncate".Truncate(10, "---") => "Long te---"


默认的截断策略Truncator.FixedLength是将输入字符串截断为特定长度,包括截断字符串的长度。 还有两种其他的截断器策略:一种用于固定数量的(字母数字)字符,另一种用于固定数量的单词。 要在截断时使用特定的截断器,前面示例中显示的两个Truncate方法都具有重载,允许您指定用于截断的ITruncator实例。 以下是有关如何使用提供的三个截断符的示例:


"Long text to truncate".Truncate(10, Truncator.FixedLength) => "Long text…"


"Long text to truncate".Truncate(10, "---", Truncator.FixedLength) => "Long te---"


"Long text to truncate".Truncate(6, Truncator.FixedNumberOfCharacters) => "Long t…"


"Long text to truncate".Truncate(6, "---", Truncator.FixedNumberOfCharacters) => "Lon---"


"Long text to truncate".Truncate(2, Truncator.FixedNumberOfWords) => "Long text…"


"Long text to truncate".Truncate(2, "---", Truncator.FixedNumberOfWords) => "Long text---"


请注意,您还可以通过实现ITruncator接口来使用创建自己的截断器。


还有一个选项可以选择是从开头(TruncateFrom.Left)还是结尾(TruncateFrom.Right)截断字符串。 如上面的示例所示,默认设置为右侧。 下面的示例显示如何从字符串的开头截断:


"Long text to truncate".Truncate(10, Truncator.FixedLength, TruncateFrom.Left) => "… truncate"


"Long text to truncate".Truncate(10, "---", Truncator.FixedLength, TruncateFrom.Left) => "---runcate"


"Long text to truncate".Truncate(10, Truncator.FixedNumberOfCharacters, TruncateFrom.Left) => "…o truncate"


"Long text to truncate".Truncate(16, "---", Truncator.FixedNumberOfCharacters, TruncateFrom.Left) => "---ext to truncate"


"Long text to truncate".Truncate(2, Truncator.FixedNumberOfWords, TruncateFrom.Left) => "…to truncate"


"Long text to truncate".Truncate(2, "---", Truncator.FixedNumberOfWords, TruncateFrom.Left) => "---to truncate"


5、格式化字符串


您可以使用FormatWith()方法设置字符串格式:


"To be formatted -> {0}/{1}.".FormatWith(1, "A") => "To be formatted -> 1/A."


这是基于String.Format的扩展方法,因此确切的规则适用于它。 如果format为null,则将引发ArgumentNullException。 如果传递的参数数目较少,则会引发String.FormatException异常。


您还可以指定区域性以显式用作FormatWith()方法的第一个参数:


"{0:N2}".FormatWith(new CultureInfo("ru-RU"), 6666.66) => "6 666,66"


如果未指定区域性,则使用当前线程的当前区域性。


6、人性化枚举


直接在枚举成员上调用ToString通常会给用户带来不理想的输出。 解决方案通常是使用DescriptionAttribute数据注释,然后在运行时读取该注释以获得更友好的输出。 那是一个很好的解决方案。 但是通常,我们只需要在枚举成员的单词之间放置一些空格-这就是String.Humanize()的优点。 对于像这样的枚举:


public enum EnumUnderTest


{


【Description("Custom description")】


MemberWithDescriptionAttribute,


MemberWithoutDescriptionAttribute,


ALLCAPITALS


}


你会得到:


// DescriptionAttribute is honored


EnumUnderTest.MemberWithDescriptionAttribute.Humanize() => "Custom description"


// In the absence of Description attribute string.Humanizer kicks in


EnumUnderTest.MemberWithoutDescriptionAttribute.Humanize() => "Member without description attribute"


// Of course you can still apply letter casing


EnumUnderTest.MemberWithoutDescriptionAttribute.Humanize().Transform(To.TitleCase) => "Member Without Description Attribute"


您不仅限于DescriptionAttribute作为自定义描述。 应用于具有字符串Description属性的枚举成员的任何属性都将计数。 这是为了帮助缺少DescriptionAttribute的平台,也允许使用DescriptionAttribute的子类。


您甚至可以配置attibute属性的名称以用作描述。


Configurator.EnumDescriptionPropertyLocator = p => p.Name == "Info"


如果需要提供本地化的描述,则可以改用DisplayAttribute数据注释。


public enum EnumUnderTest


{


【Display(Description = "EnumUnderTest_Member", ResourceType = typeof(Project.Resources))】


Member


}


你会得到:


EnumUnderTest.Member.Humanize() => "content" // from Project.Resources found under "EnumUnderTest_Member" resource key


希望这将有助于避免乱定义带有不必要属性的枚举!


7、使枚举非人性化


将字符串人性化,使其原本//代码效果参考:http://www.jhylw.com.cn/012025043.html

是人性化的枚举! 该API如下所示:

public static TTargetEnum DehumanizeTo(this string input)


用法是:


"Member without description attribute".DehumanizeTo() => EnumUnderTest.MemberWithoutDescriptionAttribute


就像Humanize API一样,它使用Description属性。 您无需提供在人性化过程中提供的外壳:它可以弄清楚。


当在编译时不知道原始Enum时,还有一个非泛型对应项:


public static Enum DehumanizeTo(this string input, Type targetEnum, NoMatch onNoMatch = NoMatch.ThrowsException)


可以像这样使用:


"Member without description attribute".DehumanizeTo(typeof(EnumUnderTest)) => EnumUnderTest.MemberWithoutDescriptionAttribute


默认情况下,两个方法都无法将提供的输入与目标枚举进行匹配时抛出NoMatchFoundException。 在非泛型方法中,您还可以通过将第二个可选参数设置为NoMatch.ReturnsNull来要求该方法返回null。


8、人性化DateTime


您可以对DateTime或DateTimeOffset的实例进行人性化,并返回一个字符串,该字符串告诉您时间上的倒退或前进时间:


DateTime.UtcNow.AddHours(-30).Humanize() => "yesterday"


DateTime.UtcNow.AddHours(-2).Humanize() => "2 hours ago"


DateTime.UtcNow.AddHours(30).Humanize() //代码效果参考:http://www.jhylw.com.cn/044135817.html

=> "tomorrow"

DateTime.UtcNow.AddHours(2).Humanize() => "2 hours from now"


DateTimeOffset.UtcNow.AddHours(1).Humanize() => "an hour from now"


Humanizer支持本地和UTC日期以及具有偏移量的日期(DateTimeOffset)。 您还可以提供要与输入日期进行比较的日期。 如果为null,它将使用当前日期作为比较基础。 另外,可以明确指定要使用的文化。 如果不是,则使用当前线程的当前UI文化。 这是API签名:


public static string Humanize(this DateTime input, bool utcDate = true, DateTime? dateToCompareAgainst = null, CultureInfo culture = null)


public static string Humanize(this DateTimeOffset input, DateTimeOffset? dateToCompareAgainst = null, CultureInfo culture = null)


此方法有许多本地化版本。 以下是一些示例:


// In ar culture


DateTime.UtcNow.AddDays(-1).Humanize() => "?"


DateTime.UtcNow.AddDays(-2).Humanize() => "? ?"


DateTime.UtcNow.AddDays(-3).Humanize() => "? 3 "


DateTime.UtcNow.AddDays(-11).Humanize() => "? 11 ?"


// In ru-RU culture


DateTime.UtcNow.AddMinutes(-1).Humanize() => "минуту назад"


DateTime.UtcNow.AddMinutes(-2).Humanize() => "2 минуты назад"


DateTime.UtcNow.AddMinutes(-10).Humanize() => "10 минут назад"


DateTime.UtcNow.AddMinutes(-21).Humanize() => "21 минуту назад"


DateTime.UtcNow.AddMinutes(-22).Humanize() => "22 минуты назад"


DateTime.UtcNow.AddMinutes(-40).Humanize() => "40 минут назад"


DateTime.Humanize有两种策略:如上所述的默认策略和基于精度的策略。 要使用基于精度的策略,您需要对其进行配置:


Configurator.DateTimeHumanizeStrategy = new PrecisionDateTimeHumanizeStrategy(precision: .75);


Configurator.DateTimeOffsetHumanizeStrategy = new PrecisionDateTimeOffsetHumanizeStrategy(precision: .75); // configure when humanizing DateTimeOffset


默认精度设置为.75,但是您也可以传递所需的精度。 将精度设置为0.75:


44 seconds =>

相关文章
|
自然语言处理 Java Go
项目总监必看:如何利用Git深度统计团队代码贡献?多语言实践教程揭秘!
项目总监必看:如何利用Git深度统计团队代码贡献?多语言实践教程揭秘!
338 0
|
敏捷开发 存储 搜索推荐
《阿里巴巴Java开发手册v1.4.0(详尽版)》更新,新增16条设计规约
阿里巴巴集团推出的《阿里巴巴Java开发手册》是阿里巴巴近万名开发同学集体智慧的结晶,以开发视角为中心,详细列举如何开发更加高效、更加容错、更加有协作性,力求知其然,更知其不然,结合正反例,让Java开发者能够提升协作效率、提高代码质量。
733947 3
|
5天前
|
JavaScript 前端开发 开发工具
如何参与开源项目以及贡献代码的流程和注意事项(2024年11月保姆级教程)
本文详细介绍了如何参与开源项目及贡献代码的流程和注意事项,包括选择项目、fork仓库、克隆到本地、阅读贡献指南、提交代码、创建Pull Request等步骤,并强调了沟通礼仪、代码质量的重要性,适合初学者参考学习。
如何参与开源项目以及贡献代码的流程和注意事项(2024年11月保姆级教程)
|
5月前
|
XML 设计模式 C#
技术心得记录:某软件公司面试题c#
技术心得记录:某软件公司面试题c#
|
6月前
|
Web App开发 小程序 JavaScript
社区每周丨基础库更新至 2.8.7及3月社区有奖活动发布
社区每周丨基础库更新至 2.8.7及3月社区有奖活动发布
74 11
|
6月前
|
小程序 安全 物联网
社区每周丨通过模板开发小程序文档更新及蚂蚁数据安全星计划推出(7.17-7.21)
社区每周丨通过模板开发小程序文档更新及蚂蚁数据安全星计划推出(7.17-7.21)
68 11
|
11月前
|
存储 运维 关系型数据库
MySQL官方特供649页顶级笔记,凝聚社区力量深入技术内幕
但凡有职场经验的兄弟都知道,大厂的面试真是一言难尽,不光看你面试时的临场发挥能力,还要分N次考你对公司业务核心技术的熟悉度。
|
关系型数据库 MySQL 程序员
卷?阿里DBA首次公开MySQL调优笔记,竟让GitHub的程序员集体叫好
对于工作了两三年的技术人员来说,在实践上已经有了比较多的积累,解决过很多问题——可能通过sys schema查询事务锁等待解决了系统的并发问题;通过设计读写分离架构扩展了应用的读性能线性扩展问题 但是作为求知欲强的技术人员,我们急切地希望知其所以然,了解MySQL到底是怎么设计的,以及为什么这样设计,读写分离架构适应的场景有哪些?什么时候建议用分库分表?等等。
114 0
|
资源调度 关系型数据库 Shell
手把手教你如何参与开源项目的协作、贡献代码: 以PolarDB开源项目为例
开源协作是一种社会进化的体现吗? 昨天体验了一下ChatGPT, 对这几个回答深有感触, 开源协作一定是未来会长期存在的, 更大规模化的人类协作模式. 所以我想写一点东西, 来帮助更多人参与开源协作.
1272 3
手把手教你如何参与开源项目的协作、贡献代码: 以PolarDB开源项目为例
|
Kubernetes 前端开发 关系型数据库
开源项目:ferry开源工单系统搭建(更新于2021 8.30)
开源项目:ferry开源工单系统搭建(更新于2021 8.30)
1405 0
开源项目:ferry开源工单系统搭建(更新于2021 8.30)