NopCommerce是啥?

nopCommerce是最好的开源电子商务购物 系统。nopCommerce免费提供。今天,它是最好和最流行的ASP.NET电子商务软件。它已被下载超过180万次!

nopCommerce是一个完全可定制的购物系统。它稳定且高度可用。nopCommerce是一个开源的电子商务解决方案,它是基于MS SQL 2008(或更高版本)后端数据库的ASP.NET(MVC)。我们易于使用的购物车解决方案特别适合已经超过现有系统的商家,并可能与您当前的网站托管商或我们的托管合作伙伴一起托管。它拥有开始通过互联网销售物理和数字产品所需的一切。

以上解释引用自该项目的Github :https://github.com/nopSolutions/nopCommerce

因为这几天没无法静心学习该项目的架构,所有只拎出该项目的CommonHelper.cs来谈谈。

1.E-Mail校验

#region Fieldsprivate static readonly Regex _emailRegex;//we use EmailValidator from FluentValidation. So let's keep them sync - https://github.com/JeremySkinner/FluentValidation/blob/master/src/FluentValidation/Validators/EmailValidator.csprivate const string _emailExpression = @"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-||_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+([a-z]+|\d|-|\.{0,1}|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])?([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$";#endregion#region Methods/// <summary>/// 检查Email(是否为空,是否超长,格式是否规范)/// </summary>/// <param name="email">The email.</param>/// <returns></returns>public static string EnsureSubscriberEmailOrThrow(string email){var output = EnsureNotNull(email);output = output.Trim();output = EnsureMaximumLength(output, 255);if (!IsValidEmail(output)){throw new NopException("Email is not valid.");}return output;}/// <summary>/// 用正则表达式校验Email/// </summary>/// <param name="email">Email to verify</param>/// <returns>true if the string is a valid e-mail address and false if it's not</returns>public static bool IsValidEmail(string email){if (string.IsNullOrEmpty(email))return false;email = email.Trim();return _emailRegex.IsMatch(email);}

这个E-mial校验的方法基本是可以直接拿过来用的,校验的正则表达式也很全面,需要用的时候可以过来copy。

2.ip地址校验

/// <summary>/// 检查该字符串是否是可用的Ip地址/// </summary>/// <param name="ipAddress">IPAddress to verify</param>/// <returns>true if the string is a valid IpAddress and false if it's not</returns>public static bool IsValidIpAddress(string ipAddress){return IPAddress.TryParse(ipAddress, out IPAddress _);}

直接使用了系统自带的IPAddress.TryParse方法,很多小伙伴还不知道吧!

3.产生指定长度的随机数字字符串

/// <summary>/// 产生一个指定长度的随机数据字符串/// </summary>/// <param name="length">Length</param>/// <returns>Result string</returns>public static string GenerateRandomDigitCode(int length){var random = new Random();var str = string.Empty;for (var i = 0; i < length; i++)str = string.Concat(str, random.Next(10).ToString());return str;}

这里的话,其实我觉得用stringbuild比直接用string更好一点,尤其是当length比较长的时候,可能用stringbuild效率更高一些。

4.产生一个随机数字

/// <summary>/// 产生一个随机数/// </summary>/// <param name="min">Minimum number</param>/// <param name="max">Maximum number</param>/// <returns>Result</returns>public static int GenerateRandomInteger(int min = 0, int max = int.MaxValue){var randomNumberBuffer = new byte[10];new RNGCryptoServiceProvider().GetBytes(randomNumberBuffer);return new Random(BitConverter.ToInt32(randomNumberBuffer, 0)).Next(min, max);}

当时不懂Random工作原理的时候,觉得这个方法简直是脱裤子放P,多此一举,搞得这么麻烦干嘛! 直接Random().Next(min,max)不就产生了一个指定范围的随机数吗?干嘛搞得这么复杂呢?

原来,Random是需要一个随机数作为“种子”的,当这个种子相同时,那么产生的随机数也是相同的,有同学肯定会说,我们平时用的时候没有指定“种子”数据,也能产生我想要的随机数啊! 其实,当我们没有指定“种子”的时候,Random时默认以当前时间作为种子的,当高并发访问的情况下,如果使用时间作为种子数据,这显然就很有可能产生相同的随机数,这显然就不那么“随机”了,所以该方法看似多余的方法都只是为了利用RNGCryptoServiceProvider().GetBytes()产生一个足够随机的byte[],然后再把该byte[]转换成数字,那么该数字就能基本不会重复了,也就是”种子”不重复,所以随机数也不会重复了。

5.检查两个数组是否相等

/// <summary>/// 检查两个数组是否相等/// </summary>/// <typeparam name="T">Type</typeparam>/// <param name="a1">Array 1</param>/// <param name="a2">Array 2</param>/// <returns>Result</returns>public static bool ArraysEqual<T>(T[] a1, T[] a2){//also see Enumerable.SequenceEqual(a1, a2);if (ReferenceEquals(a1, a2))return true;if (a1 == null || a2 == null)return false;if (a1.Length != a2.Length)return false;var comparer = EqualityComparer<T>.Default;for (var i = 0; i < a1.Length; i++){if (!comparer.Equals(a1[i], a2[i])) return false;}return true;}

搜先检测地址引用是否相同,如果相同,肯定时同一个对象,那么相等,然后是检测时否为空…..   代码很简单,就不一一说了,我们比较的时候,容易遗忘一些条件,直接走到了for循环最后一步,其实,不到迫不得已,没不要for循环。

6.给对象的指定属性赋值

/// <summary>///给对象的指定属性赋值/// </summary>/// <param name="instance">The object whose property to set.</param>/// <param name="propertyName">The name of the property to set.</param>/// <param name="value">The value to set the property to.</param>public static void SetProperty(object instance, string propertyName, object value){if (instance == null) throw new ArgumentNullException(nameof(instance));if (propertyName == null) throw new ArgumentNullException(nameof(propertyName));var instanceType = instance.GetType();var pi = instanceType.GetProperty(propertyName);if (pi == null)throw new NopException("No property '{0}' found on the instance of type '{1}'.", propertyName, instanceType);if (!pi.CanWrite)throw new NopException("The property '{0}' on the instance of type '{1}' does not have a setter.", propertyName, instanceType);if (value != null && !value.GetType().IsAssignableFrom(pi.PropertyType))value = To(value, pi.PropertyType);pi.SetValue(instance, value, new object[0]);}

我也是第一次知道,居然还能这么玩。

7.将一个值转换成目标类型

/// <summary>/// 将一个值转换成目标类型。/// </summary>/// <param name="value">The value to convert.</param>/// <param name="destinationType">The type to convert the value to.</param>/// <returns>The converted value.</returns>public static object To(object value, Type destinationType){return To(value, destinationType, CultureInfo.InvariantCulture);}/// <summary>///  将一个值转换成目标类型./// </summary>/// <param name="value">The value to convert.</param>/// <param name="destinationType">The type to convert the value to.</param>/// <param name="culture">Culture</param>/// <returns>The converted value.</returns>public static object To(object value, Type destinationType, CultureInfo culture){if (value != null){var sourceType = value.GetType();var destinationConverter = TypeDescriptor.GetConverter(destinationType);if (destinationConverter != null && destinationConverter.CanConvertFrom(value.GetType()))return destinationConverter.ConvertFrom(null, culture, value);var sourceConverter = TypeDescriptor.GetConverter(sourceType);if (sourceConverter != null && sourceConverter.CanConvertTo(destinationType))return sourceConverter.ConvertTo(null, culture, value, destinationType);if (destinationType.IsEnum && value is int)return Enum.ToObject(destinationType, (int)value);if (!destinationType.IsInstanceOfType(value))return Convert.ChangeType(value, destinationType, culture);}return value;}/// <summary>/// 将一个值转换成目标类型/// </summary>/// <param name="value">The value to convert.</param>/// <typeparam name="T">The type to convert the value to.</typeparam>/// <returns>The converted value.</returns>public static T To<T>(object value){//return (T)Convert.ChangeType(value, typeof(T), CultureInfo.InvariantCulture);return (T)To(value, typeof(T));}

有了这个方法,我们就不用傻傻想着用Convent….到底Convernt点什么呢?哈哈,直接To<T>(),是不是很帅?

8.删除目录

/// <summary>///  深度优先的递归删除/// </summary>/// <param name="path">Directory path</param>public static void DeleteDirectory(string path){if (string.IsNullOrEmpty(path))throw new ArgumentNullException(path);//find more info about directory deletion//and why we use this approach at https://stackoverflow.com/questions/329355/cannot-delete-directory-with-directory-deletepath-trueforeach (var directory in Directory.GetDirectories(path)){DeleteDirectory(directory);}try{Directory.Delete(path, true);}catch (IOException){Directory.Delete(path, true);}catch (UnauthorizedAccessException){Directory.Delete(path, true);}}

一开始,我也不明白为什么要弄得这么复杂,要删除目录,直接Directory.Delete(path)就好了不是吗? 其实不是的,如果目录不为空,会报System.IO.IOException: The directory is not empty.的错误的,所以要递归,层层删除,据说Win系统的资源管理器,删除目录,其实就是这个逻辑实现的。

9.获取两个Datetime之间的年份间隔

/// <summary>/// 获取两个时间之间相差的年份/// </summary>/// <param name="startDate"></param>/// <param name="endDate"></param>/// <returns></returns>public static int GetDifferenceInYears(DateTime startDate, DateTime endDate){//source: http://stackoverflow.com/questions/9/how-do-i-calculate-someones-age-in-c//this assumes you are looking for the western idea of age and not using East Asian reckoning.var age = endDate.Year - startDate.Year;if (startDate > endDate.AddYears(-age))age--;return age;}

对,如果endDate.Year - startDate.Year是不对的,就好像你是去年的8月份出生的,而现在才五月份,那么你现在还不能称为1岁一样的道理。同样的方法还可以用来获取月、日、时、分、秒的间隔。

10 虚拟路径转物理路径

/// <summary>/// 映射虚拟路径到物理路径/// </summary>/// <param name="path">The path to map. E.g. "~/bin"</param>/// <returns>The physical path. E.g. "c:\inetpub\wwwroot\bin"</returns>public static string MapPath(string path){path = path.Replace("~/", "").TrimStart('/').Replace('/', '\\');
  CommonHelper.BaseDirectory = hostingEnvironment.ContentRootPath;
            return Path.Combine(BaseDirectory ?? string.Empty, path);}

大致就是这么多,可能以上方法大家都知道,但是自己写出来可能不够巧妙(老江湖除外),记录下来,希望对大家有所帮助,也用于自我加深映像。

有兴趣的可以去github上下载nopcommerce的源码来看看。

转:https://www.cnblogs.com/CoderAyu/p/8982842.html

NopCommerce开源项目中很基础但是很实用的C# Helper方法相关推荐

  1. 开源项目中经常出现的七种错误

    启动一个新的开源项目可能会遇到一些困难.也许你脑子里有一个很棒的想法,但是想把它们变成富有成效的.健康的.吸引人的社区还需要做很多工作.令人叹息的是,相同的错误总是被无代价的重复,出现低级错误是团队中 ...

  2. 如何充分利用开源项目_5个技巧:在开源项目中利用以用户为中心的设计

    如何充分利用开源项目 当我刚开始在开放技术学院 (OTI)工作时,我始终受到以下问题的挑战:"为什么UX设计师为什么要在开源组织工作?" 在我看来,事实是几乎所有设计和可用性工作本 ...

  3. 前端大型开源项目_在大型开源项目中管理问题

    前端大型开源项目 We're honored by the amount of positive feedback we get from folks using Flutter. As one of ...

  4. 我们在开源项目中是怎样埋彩蛋的

    今天的 AntDesign 圣诞节彩蛋事件确实炸开了锅,加彩蛋的初衷是好的,只是这次玩过了火. 在开源软件中,加彩蛋是一种乐趣,并不为奇,同为知名 UI 组件库的 iView 项目,也经常在 文档 中 ...

  5. 如何参与到GitHub开源项目中

    最近一年开源项目特别的热,很多技术大会或论坛都以开源项目作为主题进行探讨,可见这是一种趋势.而Github作为开源项目的著名托管地,可谓无人不知,越来越多的个人和公司纷纷加入到Github的大家族里来 ...

  6. 喜报丨京东科技主导的开源项目ShardingSphere荣登报告榜单国人主导开源项目中活跃度第五名!...

    1月19日,开源社发布<2020 中国开源年度报告>.在报告中,ShardingSphere荣登所有国人主导开源项目中活跃度第五名,作为 Apache 软件基金会下属的国人主导的开源项目中 ...

  7. 从15000个Python开源项目中精选的Top30,Github平均star为3707,赶紧收藏!

    翻译 | AI科技大本营(ID:rgznai100) 参与 | SuiSui 继推出2017年机器学习开源项目Top 30榜单后,Mybridge AI又推出了一个Python开源项目Top 30榜单 ...

  8. 收藏!15000个Python开源项目中精选Top30!

    来源:授权自AI科技大本营(ID:rgznai100) 本文长度为1700字,建议阅读6分钟 本文基于项目质量.用户参与度以及其他因素为你列出Python开源项目Top 30,建议收藏. 继推出201 ...

  9. 15000个开源项目中挑选Top 12

    15000个开源项目中挑选Top 12,第一就是-- 2018-01-17 

最新文章

  1. 程序员锁死服务器致公司倒闭当事人逐条反驳:这锅我不背
  2. MySQL存储过程中的3种循环
  3. ASP.NET的錯誤類型及錯誤處理方式
  4. 一道面试题:遇到大规模Oracle坏块该怎么处理?
  5. asp手机拍照显示_设备 | UNIJET募资约6600万元,用于大尺寸显示领域的新一代喷墨打印技术...
  6. C#利用Process关闭所有的IE窗口
  7. spring源码-bean加载整体流程
  8. 慕课软件质量保证与测试(第二章.课后作业)
  9. 华为光猫HG8120C的一些配置文件
  10. iOS HealthKit
  11. 炫酷又实用的发送邮箱链接修改密码
  12. DeeCamp2022正式开营!李开复、张亚勤亲授大师课 | 创新事
  13. java开发必备基础
  14. htts 及 tomcat ssl配置
  15. Leetcode 309. Best Time to Buy and Sell Stock with Cooldown
  16. 用Mouse_event()来模拟鼠标操作
  17. 雀巢近260款畅销产品集体亮相第三届进博会
  18. Unity3d如何实现四格漫画动态播放
  19. 如何杀掉“熊猫烧香”
  20. STM32F103学习笔记(1)掌握GPIO操作—输出模式(推挽/开漏)

热门文章

  1. OpenCV YOLO DNN(yolo_object_detection)
  2. Qt Creator自定义构建过程
  3. Qt Creator将应用程序部署到Android设备
  4. Qt Creator使用CVS
  5. C++以字符串形式返回第N个斐波那契的算法(附完整源码)
  6. QT的QSGGeometry类的使用
  7. QT的QDesignerCustomWidgetInterface类的使用
  8. 「SLAM」十四讲:第1讲 预备知识
  9. pytroch 数据增量 transforms的二十二个方法
  10. 04_Pytorch生态、PyTorch能做什么、PyTorch之Autograd、autograd案例、GPU加速案例