NopCommerce开源项目中很基础但是很实用的C# Helper方法
刚过了个五一,在杭州到处看房子,不知道杭州最近怎么了,杭州买房的人这么多,房价涨得太厉害,这几年翻倍翻倍地涨,刚过G20,又要亚运会,让我这样的刚需用户买不起,也买不到房子,搞得人心惶惶,太恐怖了,心好累。
这几天,因为这件事情感觉人都是懵的,无法静心学习复杂的东西,所以就看看一些基础,学习学习NopCommerce的CommonHelper都写了些啥,看看别人的代码巧在哪里,妙在哪里。
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 Fields private 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.cs
private 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, ); 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 = ; i < length; i++)
str = string.Concat(str, random.Next().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 = , int max = int.MaxValue)
{
var randomNumberBuffer = new byte[];
new RNGCryptoServiceProvider().GetBytes(randomNumberBuffer);
return new Random(BitConverter.ToInt32(randomNumberBuffer, )).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 = ; 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[]);
}
我也是第一次知道,居然还能这么玩。
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-true foreach (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的源码来看看。
另外,杭州买房,预算有限,杭州城区估计是买不起了,现在在纠结海宁、安吉、德清、桐乡、桐庐等这样的周边地区,如果有杭州有买房经验的同行大哥希望能给小弟一点指点,哈哈~~
NopCommerce开源项目中很基础但是很实用的C# Helper方法的更多相关文章
- [转]C,C++开源项目中的100个Bugs
[转]C,C++开源项目中的100个Bugs http://tonybai.com/2013/04/10/100-bugs-in-c-cpp-opensource-projects/ 俄罗斯OOO P ...
- android studio 使用jar包,arr包和怎么使用githup开源项目中的aar包或module
我这里的android studio的版本是2.2.3版本 一.现在大家都用android studio了,就有人问怎么使用jar包 其实使用jar包比较简单 直接吧jar放入工程的app目录下的li ...
- dotnet 是 前30个增长最快速度的开源项目中排名第一的开发平台
CNCF 的博客 发了一篇文章 <Update on CNCF and Open Source Project Velocity 2020>,中文翻译参见 2020年CNCF和开源项目开发 ...
- Java项目中每一个类都可以有一个main方法
Java项目中每一个类都可以有一个main方法,但只有一个main方法会被执行,其他main方法可以对类进行单元测试. public class StaticTest { public static ...
- 细数Android开源项目中那些频繁使用的并发库中的类
这篇blog旨在帮助大家 梳理一下前面分析的那些开源代码中喜欢使用的一些类,这对我们真正理解这些项目是有极大好处的,以后遇到类似问题 我们就可以自己模仿他们也写 出类似的代码. 1.ExecutorS ...
- C,C++开源项目中的100个Bugs
俄罗斯OOO Program Verification Systems公司用自己的静态源码分析产品PVS-Studio对一些知名的C/C++开源项目,诸如Apache Http Server.Chro ...
- java 基础题 很基础, 很有趣
都是一些非常非常基础的题,是我最近参加各大IT公司笔试后靠记忆记下来的,经过整理献给与我一样参加各大IT校园招聘的同学们,纯考Java基础功底, 老手们就不用进来了,免得笑话我们这些未出校门的孩纸们, ...
- Jquery和Javascript 实际项目中写法基础-弹出窗和弹出层 (4)
一.实际项目中有很多如下界面效果. 二.该效果可以归结为弹出窗或者弹出层来实现的,为什么这么说?看如下代码: <!DOCTYPE html> <html> & ...
- 项目中lua(基础)
关于项目中lua任务(某些没弄懂,但lua上耗费时间有点长了不看了) 这段时间看了lua语法和项目中lua应用 .在lua中注册c库,在lua5.2中好像都是注册c库,相当于在lua中定义一个tabl ...
随机推荐
- UNIX网络编程——非阻塞connect: Web客户程序
非阻塞的connect的实现例子出自Netscape的Web客户程序.客户先建立一个与某个Web服务器的HTTP连接,再获取一个主页.该主页往往含有多个对于其他网页的引用.客户可以使用非阻塞conne ...
- Dynamics CRM 2015Online Update1 new feature之 插件跟踪日志
在最新的CRM2015Online Update1版本中加入了一个新功能-插件跟踪日志,与其说是新功能更应该说是对原有功能的加强,因为ITracingService这个接口在2013中已经引入了, ...
- Android开发学习之路--Activity之生命周期
其实这篇文章应该要在介绍Activity的时候写的,不过那个时候还不怎么熟悉Activity,还是在这里详细介绍下好了.还是参考下官方文档的图吧: 从上面的流程,我们可以看出首先就是打开APP,开始执 ...
- UNIX网络编程——套接字选项(setsockopt)
setsockopt的一些用法: close socket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket: BOOL bReuseaddr=TRUE; setsockop ...
- 【Android 应用开发】 Android 相关代码规范 更新中 ...
. 简介 : Android 常用的代码结构, 包括包的规范, 测试用例规范, 数据库模块常用编写规范; 参考 : 之前写的一篇博客 [Android 应用开发] Application 使用分析 ; ...
- Web Service进阶(一)运行原理
利用清明小假期,温习了一遍Web Service的相关内容,对其工作原理进行了简要总结.以供有需求的朋友和自己日后参考.文章若有不当之处,敬请朋友们提出宝贵建议,以求共勉. Web服务中,我们应该首先 ...
- UNIX环境高级编程——select、poll和epoll
一.select select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,事实上从现在看来,这也是它所剩不多的优点之一. select的一个缺点在于单个进程能够监视的文件描述符的数量 ...
- 【一天一道LeetCode】#100. Same Tree(100题大关)
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given t ...
- Java进阶(二十七)使用Dom4j解析XML文件
使用Dom4j解析XML文件 写在前面的话 由于论文实验要求,需要实现操作XML文档,为此想到了dom4j这个工具,使用之后深感受益.在此分享给大家,以此共勉. 注:本文转载自http://blog. ...
- 【Qt编程】基于Qt的词典开发系列--后序
从去年八月份到现在,总算完成了词典的编写以及相关技术文档的编辑工作.从整个过程来说,文档的编写比程序的实现耗费的时间更多.基于Qt的词典开发系列文章,大致包含了在编写词典软件过程中遇到的技术重点与难点 ...