解决 Linq 的 lambda 表达式排序不够灵活问题。

namespace Utility.Linq
{
    public static class QueryableExtend
    {
        /// <summary>
        /// 根据键按升序对序列的元素排序
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型</typeparam>
        /// <param name="source">一个要排序的值序列</param>
        /// <param name="field">排序字段</param>
        /// <returns>一个 System.Linq.IOrderedQueryable T,根据键对其元素排序。</returns>
        public static IQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string field)
        {
            source = source.OrderBy(field, "OrderBy");
            return source;
        }

        /// <summary>
        /// 根据键按降序对序列的元素排序
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型</typeparam>
        /// <param name="source">一个要排序的值序列</param>
        /// <param name="field">排序字段</param>
        /// <returns>一个 System.Linq.IOrderedQueryable T,根据键对其元素排序。</returns>
        public static IQueryable<TSource> OrderByDescending<TSource>(this IQueryable<TSource> source, string field)
        {
            source = source.OrderBy(field, "OrderByDescending");
            return source;
        }

        /// <summary>
        /// 根据某个键按降序对序列中的元素执行后续排序。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型</typeparam>
        /// <param name="source">一个要排序的值序列</param>
        /// <param name="field">排序字段</param>
        /// <param name="isDescending">是否倒序(可选,默认否)</param>
        /// <returns>一个 System.Linq.IOrderedQueryable T,根据键对其元素排序。</returns>
        public static IQueryable<TSource> ThenBy<TSource>(this IQueryable<TSource> source, string field)
        {
            source = source.OrderBy(field, "ThenBy");
            return source;
        }

        /// <summary>
        /// 使用指定的比较器按降序对序列中的元素执行后续排序。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型</typeparam>
        /// <param name="source">一个要排序的值序列</param>
        /// <param name="field">排序字段</param>
        /// <param name="isDescending">是否倒序(可选,默认否)</param>
        /// <returns>一个 System.Linq.IOrderedQueryable T,根据键对其元素排序。</returns>
        public static IQueryable<TSource> ThenByDescending<TSource>(this IQueryable<TSource> source, string field)
        {
            source = source.OrderBy(field, "ThenByDescending");
            return source;
        }

        /// <summary>
        /// 根据键按升序对序列的元素排序
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型</typeparam>
        /// <param name="source">一个要排序的值序列</param>
        /// <param name="field">排序字段</param>
        /// <param name="methodName">排序方法名</param>
        /// <returns>一个 System.Linq.IOrderedQueryable T,根据键对其元素排序。</returns>
        public static IQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string field, string methodName)
        {
            if(source == null)
            {
                throw new ArgumentException("source");
            }
            if(field == null)
            {
                throw new ArgumentException("field");
            }
            if(methodName == null)
            {
                throw new ArgumentException("methodName");
            }
            Type entityType = typeof(TSource);
            ParameterExpression parameterExpression = Expression.Parameter(entityType, entityType.FullName);
            Expression propertyExpression = Expression.Property(parameterExpression, entityType.GetProperty(field));
            Expression expression = Expression.Lambda(propertyExpression, parameterExpression);
            PropertyInfo propertyInfo = entityType.GetProperty(field);
            Type propertyType = propertyInfo.PropertyType;
            Expression expr = Expression.Call(typeof(Queryable), methodName, new Type[] { entityType, propertyType }, source.Expression, expression);
            source = source.Provider.CreateQuery<TSource>(expr);
            return source;
        }
    }
}

namespace Provider.Payment.Alipay
{
    public class AlipayUtil
    {
        /// <summary>
        /// 生成签名
        /// 相关文档:https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.vwCvxF&treeId=62&articleId=104741&docType=1
        /// </summary>
        /// <param name="obj">要签名的对象</param>
        /// <param name="signKey">签名密匙</param>
        /// <returns>签名字符串</returns>
        public static string GenerateSign(object entity, string signKey)
        {
            SortedDictionary<string, object> sorted = GetSortedDictionary(entity);
            return GenerateSign(sorted, signKey);
        }
        /// <summary>
        /// 生成签名
        /// </summary>
        /// <remarks>
        /// 相关文档:https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.vwCvxF&treeId=62&articleId=104741&docType=1
        /// </remarks>
        /// <param name="obj">要签名的对象</param>
        /// <param name="signKey">签名密匙</param>
        /// <returns>签名字符串</returns>
        public static string GenerateSign(SortedDictionary<string, object> sorted, string signKey)
        {
            StringBuilder builder = new StringBuilder();
            foreach (KeyValuePair<string, object> pair in sorted)
            {
                if (pair.Key != "sign" && pair.Key != "sign_type")
                {
                    object value = pair.Value;
                    Type type = pair.Value.GetType();
                    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                    {
                        type = type.GetGenericArguments()[0];
                    }
                    if (type == typeof(DateTime))
                    {
                        value = Convert.ToDateTime(value).ToString("yyyy-MM-dd HH:mm:ss");
                    }
                    builder.Append(pair.Key + "=" + value + "&");
                }
            }
            string str = builder.Remove(builder.Length - 1, 1).ToString() + signKey;
            string sign = MD5Encrypt(str);
            return sign;
        }
        /// <summary>
        /// 获得属性值并排序
        /// </summary>
        /// <param name="entity">参数</param>
        /// <returns></returns>
        protected static SortedDictionary<string, object> GetSortedDictionary(object entity)
        {
            Type type = entity.GetType();
            PropertyInfo[] propertys = type.GetProperties();
            SortedDictionary<string, object> sorted = new SortedDictionary<string, object>();
            foreach (PropertyInfo property in propertys)
            {
                Type propertyType = property.GetType();
                object objValue = null;
                if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    bool HasValue = (bool)type.GetProperty("HasValue").GetValue(entity, null);
                    if (HasValue)
                    {
                        objValue = type.GetProperty("Value").GetValue(entity, null);
                    }
                }
                else
                {
                    objValue = property.GetValue(entity, null);
                }
                string value = (objValue ?? "").ToString();
                if (!String.IsNullOrEmpty(value))
                {
                    sorted.Add(property.Name, value);
                }
            }
            return sorted;
        }
        /// <summary>
        /// MD5加密
        /// </summary>
        protected static string MD5Encrypt(string input)
        {
            MD5 md5 = MD5.Create();
            byte[] bytes = Encoding.UTF8.GetBytes(input);
            byte[] buffer = md5.ComputeHash(bytes);
            StringBuilder builder = new StringBuilder();
            foreach (byte b in buffer)
            {
                builder.Append(b.ToString("x2"));
            }
            return builder.ToString();
        }
    }
}

using System;
using System.Drawing;
using System.Drawing.Imaging;

namespace Utility
{
    public class ImageUtil
    {
        ///<summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="originalImagePath">源图路径(物理路径)</param>
        /// <param name="thumbnailPath">缩略图路径(物理路径)</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <param name="mode">生成缩略图的方式</param>    
        public static void MakeThumbnail(string originalImagePath, string thumbnailPath, int width, int height, string mode)
        {
            Image originalImage = Image.FromFile(originalImagePath);

            int towidth = width;
            int toheight = height;

            int x = 0;
            int y = 0;
            int ow = originalImage.Width;
            int oh = originalImage.Height;

            switch (mode)
            {
                case "HW"://指定高宽缩放(可能变形)                
                    break;
                case "W"://指定宽,高按比例                    
                    toheight = originalImage.Height * width / originalImage.Width;
                    break;
                case "H"://指定高,宽按比例
                    towidth = originalImage.Width * height / originalImage.Height;
                    break;
                case "Cut"://指定高宽裁减(不变形)                
                    if ((double)originalImage.Width / (double)originalImage.Height > (double)towidth / (double)toheight)
                    {
                        oh = originalImage.Height;
                        ow = originalImage.Height * towidth / toheight;
                        y = 0;
                        x = (originalImage.Width - ow) / 2;
                    }
                    else
                    {
                        ow = originalImage.Width;
                        oh = originalImage.Width * height / towidth;
                        x = 0;
                        y = (originalImage.Height - oh) / 2;
                    }
                    break;
                default:
                    break;
            }
            //新建一个bmp图片
            Image bitmap = new Bitmap(towidth, toheight);
            //新建一个画板
            Graphics g = System.Drawing.Graphics.FromImage(bitmap);
            //设置高质量插值法
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
            //设置高质量,低速度呈现平滑程度
            //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQualityBilinear
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            //清空画布并以透明背景色填充
            g.Clear(Color.Transparent);
            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight), new Rectangle(x, y, ow, oh), GraphicsUnit.Pixel);
            try
            {
                //以jpg格式保存缩略图
                bitmap.Save(thumbnailPath, ImageFormat.Jpeg);
            }
            catch (System.Exception e)
            {
                throw e;
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
            }
        }
    }
}

这是微软官方提供的解决方案,支持简体中午,繁体中文,韩语和日语。

需要安装依赖的 Visual Studio International Pack

下载地址:https://www.microsoft.com/zh-CN/download/details.aspx?id=15251

using System;
using System.Data;
using System.Configuration;
using Microsoft.International.Converters.PinYinConverter;

namespace Utility.Convert
{
    /// <summary>
    ///ChineseConvert 的摘要说明
    /// </summary>
    public class ChineseConvert
    {
        public ChineseConvert() { }

        /// <summary>
        /// 汉字转化为拼音
        /// </summary>
        /// <param name="str">汉字</param>
        /// <returns>全拼</returns>
        public static string GetPinyin(string str)
        {
            string r = string.Empty;
            foreach (char obj in str)
            {
                try
                {
                    ChineseChar chineseChar = new ChineseChar(obj);
                    string t = chineseChar.Pinyins[0].ToString();
                    r += t.Substring(0, t.Length - 1);
                }
                catch
                {
                    r += obj.ToString();
                }
            }
            return r;
        }

        /// <summary>
        /// 汉字转化为拼音首字母
        /// </summary>
        /// <param name="str">汉字</param>
        /// <returns>首字母</returns>
        public static string GetFirstPinyin(string str)
        {
            string r = string.Empty;
            foreach (char obj in str)
            {
                try
                {
                    ChineseChar chineseChar = new ChineseChar(obj);
                    string t = chineseChar.Pinyins[0].ToString();
                    r += t.Substring(0, 1);
                }
                catch
                {
                    r += obj.ToString();
                }
            }
            return r;
        }

    }
}

/// <summary>
/// 判断是否是图片
/// </summary>
public static bool IsPicture(Stream stream)
{
	try
	{
		byte[] buffer = new byte[2];
		stream.Read(buffer, 0, 2);
		string fileClass = buffer[0].ToString() + buffer[1].ToString();

		//255216是jpg;7173是gif;6677是BMP,13780是PNG;7790是exe,8297是rar   
		string[] fileType = { "255216", "7173", "13780", "6677" };
		return fileType.Contains(fileClass);
	}
	catch
	{
		return false;
	}
}

public class FileUtil
{
	[DllImport("kernel32.dll")]
	private static extern IntPtr _lopen(string lpPathName, int iReadWrite);

	[DllImport("kernel32.dll")]
	public static extern bool CloseHandle(IntPtr hHandle);


	private const int OF_READWRITE = 2;
	private const int OF_SHARE_DENY_NONE = 0x40;
	private static readonly IntPtr HFILE_ERROR = new IntPtr(-1);
	
	/// <summary>
	/// 查看文件是否被占用
	/// </summary>
	/// <param name="filePath">文件路径</param>
	/// <returns></returns>
	public static bool IsOccupied(string filePath)
	{
		IntPtr vHandle = _lopen(filePath, OF_READWRITE | OF_SHARE_DENY_NONE);
		if(vHandle == HFILE_ERROR)
		{
			return true;
		}
		CloseHandle(vHandle);
		return false;
	}
}

微软官方从.NET Framework 4之后不再支持System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(string password, string passwordFormat)方法。MD5加密需要自行实现。需要注意的是该方法加密结果是小写,而
HashPasswordForStoringInConfigFile加密结果是大写

public static string MD5Encrypt(string input)
{
	StringBuilder builder = new StringBuilder();
        using (MD5CryptoServiceProvider md5Crypto = new MD5CryptoServiceProvider())
        {
            byte[] data = md5Crypto.ComputeHash(Encoding.UTF8.GetBytes(input));
            for (int i = 0; i < data.Length; i++)
            {
                builder.Append(data[i].ToString("x2"));
            }
        }
        return builder.ToString();
}

using System;
using System.Text;
using System.Security.Cryptography;

namespace Utility.Security
{
    /// <summary>
    /// DES加密/解密类。
    /// </summary>
    public class DESEncrypt
    {
        /// <summary> 
        /// 加密数据 
        /// </summary> 
        public static string Encrypt(string Text, string sKey)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] inputByteArray;
            inputByteArray = Encoding.Default.GetBytes(Text);
            des.Key = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
            des.IV = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();
            StringBuilder ret = new StringBuilder();
            foreach (byte b in ms.ToArray())
            {
                ret.AppendFormat("{0:X2}", b);
            }
            return ret.ToString();
        }

        /// <summary> 
        /// 解密数据 
        /// </summary> 
        public static string Decrypt(string Text, string sKey)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            int len;
            len = Text.Length / 2;
            byte[] inputByteArray = new byte[len];
            int x, i;
            for (x = 0; x < len; x++)
            {
                i = Convert.ToInt32(Text.Substring(x * 2, 2), 16);
                inputByteArray[x] = (byte)i;
            }
            des.Key = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
            des.IV = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();
            return Encoding.Default.GetString(ms.ToArray());
        }
    }
}

public sealed class AcrobatUtil
{
	public string ConvertToExecl(string inputFileName, string outputFileName)
	{
		//判断文件是否存在
		if (!File.Exists(inputFileName))
		{
			return "File Is Missing";
		}
		try
		{
			//判断是否已经安装Acrobat
			string acrobatPath = GetAppPath();
			if (acrobatPath == null)
			{
				return "Adobe Acrobat not installed.";
			}

			var aVDoc = new AcroAVDoc();
			aVDoc.Open(inputFileName, "");
			CAcroPDDoc PDDoc = (CAcroPDDoc)aVDoc.GetPDDoc();
			object jsObj = PDDoc.GetJSObject();
			var jsObjType = jsObj.GetType();
			//另存为
			jsObjType.InvokeMember(
							"saveAs",
							BindingFlags.InvokeMethod |
							BindingFlags.Public |
							BindingFlags.Instance,
							null, jsObj, new object[] { outputFileName, "com.adobe.acrobat.xlsx" });
/*
另存为更多格式
html htm      com.adobe.acrobat.html
jpeg jpg      com.adobe.acrobat.jpeg
docx          com.adobe.acrobat.docx
doc           com.adobe.acrobat.doc
png           com.adobe.acrobat.png
ps            com.adobe.acrobat.ps
rft           com.adobe.acrobat.rft
xlsx          com.adobe.acrobat.xlsx
xls           com.adobe.acrobat.spreadsheet
txt           com.adobe.acrobat.accesstext
tiff tif      com.adobe.acrobat.tiff
xml           com.adobe.acrobat.xml-1-00
*/
			//关闭文档
			aVDoc.Close(1);
		}
		catch (Exception ex)
		{
			return "Error:" + ex.Message;
		}
		return null;
	}
	
	//获取Acrobat安装路径
	private string GetAppPath()
	{
		string acrobatPath = null;
		using (RegistryKey acrobatRegistryKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Adobe\Adobe Acrobat"))
		{
			if (acrobatRegistryKey == null)
			{
				return acrobatPath;
			}
			string acrobatVersion = acrobatRegistryKey.GetValue("TrackName").ToString();
			using (RegistryKey acrobatInstallPathRegistryKey = acrobatRegistryKey.OpenSubKey(acrobatVersion + @"\InstallPath"))
			{
				if (acrobatInstallPathRegistryKey == null)
				{
					return acrobatPath;
				}
				acrobatPath = acrobatInstallPathRegistryKey.GetValue("").ToString() + @"\Acrobat.exe";
			}
		}
		return acrobatPath;
	}
}