using CAPI.Custom.Entities; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Data; using System.Data.Common; using System.Data.Entity; using System.Dynamic; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace CAPI.Custom { public static class Extensions { public static bool IsNull(this object value) { return null == value; } public static bool IsNotNull(this object value) { return !value.IsNull(); } public static bool IsEmpty(this IEnumerable value) { return value.IsNull() || !value.Any(); } public static bool IsNotEmpty(this IEnumerable value) { return !value.IsEmpty(); } #region strings public static bool IsEmpty(this string value) { return string.IsNullOrWhiteSpace(value); } public static bool IsNotEmpty(this string value) { return !value.IsEmpty(); } public static bool EqualsIgnoreCase(this string value, string other) { if (value.IsNull() && other.IsNull()) return true; if (value.IsNull()) return false; return value.Equals(other, StringComparison.OrdinalIgnoreCase); } public static string StringJoin(this IEnumerable value, string separator, bool removeEmptyValues = true) { if (removeEmptyValues) { string[] temp = string.Join(separator, value) .Split(new string[] { separator }, StringSplitOptions.RemoveEmptyEntries); return string.Join(separator, temp); } return string.Join(separator, value.ToArray()); } public static string TrimString(this string value) { if (value.IsEmpty()) return string.Empty; return value.Trim(); } /// /// Turns "PascalCasedString" to "Pascal Cased String" /// /// /// public static string SplitPascalCase(this string value) { return Regex.Replace(value, "([A-Z])", " $1", RegexOptions.Compiled).Trim(); } public static string NullOrEmptyCoalesce(this string value, params string[] others) { if (value.IsNotEmpty()) return value; foreach(string val in others) { if (val.IsNotEmpty()) return val; } return string.Empty; } public static string ToUpperNonEmpty(this string value) { if (value.IsEmpty()) return string.Empty; return value.ToUpper().TrimString(); } /// /// Removes all line breaks and reduces multiple white spaces. /// /// /// public static string Flatten(this string value) { var newLinePattern = @"[\n\r]+"; var multipleSpacePattern = @"\s+"; var newValue = Regex.Replace(value, newLinePattern, " "); newValue = Regex.Replace(newValue, multipleSpacePattern, " "); return newValue; } public static Guid ToGuid(this string value) { // Create a new instance of the MD5CryptoServiceProvider object. MD5 md5Hasher = MD5.Create(); // Convert the input string to a byte array and compute the hash. byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(value)); return new Guid(data); } #endregion #region string parsing static Regex regexInt = new Regex(@"\d+"); public static int? TryParseInt(this string value) { int result = 0; var matches = regexInt.Matches(value).Cast().Select(m => m.Value); string newVal = matches.StringJoin(""); return int.TryParse(newVal, out result) ? result : (int?)null; } static Regex regexDecimal = new Regex(@"(\d+)|\."); public static decimal? TryParseDecimal(this string value) { decimal result = 0; var matches = regexDecimal.Matches(value).Cast().Select(m => m.Value); string newVal = matches.StringJoin(""); return decimal.TryParse(newVal, out result) ? result : (decimal?)null; } #endregion #region TimeSpans /// /// Multiplies a timespan by an integer value /// public static TimeSpan Multiply(this TimeSpan multiplicand, int multiplier) { return TimeSpan.FromTicks(multiplicand.Ticks * multiplier); } /// /// Multiplies a timespan by a double value /// public static TimeSpan Multiply(this TimeSpan multiplicand, double multiplier) { return TimeSpan.FromTicks((long)(multiplicand.Ticks * multiplier)); } #endregion public static DateTime GetValueOrSqlMin(this DateTime? value) { return value.HasValue ? value.Value : BusinessUtils.SqlDateTimeMinValue; } public static string ToJson(this object value, Newtonsoft.Json.Formatting formatting = Newtonsoft.Json.Formatting.None) { if (value.IsNull()) return string.Empty; return Newtonsoft.Json.JsonConvert.SerializeObject(value, formatting); } public static string ToJsonIndented(this object value) { return value.ToJson(Newtonsoft.Json.Formatting.Indented); } } public static class IQueryableExtensions { public static IEnumerable WhereIf(this IEnumerable source, bool condition, Func predicate) { if (condition) return source.Where(predicate); else return source; } public static IEnumerable WhereIf(this IEnumerable source, bool condition, Func predicate) { if (condition) return source.Where(predicate); else return source; } /// /// OrderBy with string paramter /// /// /// /// /// public static IOrderedQueryable OrderBy(this IQueryable query, string propertyName) { var entityType = typeof(TSource); //Create x=>x.PropName var propertyInfo = entityType.GetProperty(propertyName); ParameterExpression arg = Expression.Parameter(entityType, "x"); MemberExpression property = Expression.Property(arg, propertyName); var selector = Expression.Lambda(property, new ParameterExpression[] { arg }); //Get System.Linq.Queryable.OrderBy() method. var enumarableType = typeof(System.Linq.Queryable); var method = enumarableType.GetMethods() .Where(m => m.Name == "OrderBy" && m.IsGenericMethodDefinition) .Where(m => { var parameters = m.GetParameters().ToList(); //Put more restriction here to ensure selecting the right overload return parameters.Count == 2;//overload that has 2 parameters }).Single(); //The linq's OrderBy has two generic types, which provided here MethodInfo genericMethod = method .MakeGenericMethod(entityType, propertyInfo.PropertyType); /*Call query.OrderBy(selector), with query and selector: x=> x.PropName Note that we pass the selector as Expression to the method and we don't compile it. By doing so EF can extract "order by" columns and generate SQL for it.*/ var newQuery = (IOrderedQueryable)genericMethod .Invoke(genericMethod, new object[] { query, selector }); return newQuery; } } public static class EncryptionExtensions { private static readonly string EncryptionKey = "bc156e97-77e1-4e66-981e-2b610e5f0d97"; public static string Encrypt(this string clearText) { byte[] clearBytes = Encoding.Unicode.GetBytes(clearText); using (Aes encryptor = Aes.Create()) { Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); encryptor.Key = pdb.GetBytes(32); encryptor.IV = pdb.GetBytes(16); using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write)) { cs.Write(clearBytes, 0, clearBytes.Length); cs.Close(); } clearText = Convert.ToBase64String(ms.ToArray()); } } return clearText; } public static string Decrypt(string cipherText) { cipherText = cipherText.Replace(" ", "+"); byte[] cipherBytes = Convert.FromBase64String(cipherText); using (Aes encryptor = Aes.Create()) { Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); encryptor.Key = pdb.GetBytes(32); encryptor.IV = pdb.GetBytes(16); using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(cipherBytes, 0, cipherBytes.Length); cs.Close(); } cipherText = Encoding.Unicode.GetString(ms.ToArray()); } } return cipherText; } } public static class ReflectionExtensions { public static bool HasProperty(this object source, string propertyName) { if (source == null) throw new ArgumentNullException("source"); var sourceType = source.GetType(); return sourceType.GetProperty(propertyName) != null; } public static T GetPropertyValue(this object source, string property) { if (source == null) throw new ArgumentNullException("source"); var sourceType = source.GetType(); var sourceProperties = sourceType.GetProperties(); var propertyValue = (from s in sourceProperties where s.Name.Equals(property) select s.GetValue(source, null)).FirstOrDefault(); return propertyValue != null ? (T)propertyValue : default(T); } public static void SetPropertyValue(this object source, string propertyName, object value) { if (source == null) throw new ArgumentNullException("source"); var sourceType = source.GetType(); var property = sourceType.GetProperty(propertyName); property.SetValue(source, value); } } public static class DataTableExtensions { public static bool IsEmpty(this DataTable tbl) { if (null == tbl) return true; return tbl.Rows.Count == 0; } public static List CreateListFromTable(this DataTable tbl) where T : new() { // define return list List lst = new List(); // go through each row foreach (DataRow r in tbl.Rows) { // add to the list lst.Add(CreateItemFromRow(r)); } // return the list return lst; } // function that creates an object from the given data row public static T CreateItemFromRow(DataRow row) where T : new() { // create a new object T item = new T(); // set the item SetItemFromRow(item, row); // return return item; } public static void SetItemFromRow(T item, DataRow row) where T : new() { // go through each column foreach (DataColumn c in row.Table.Columns) { // find the property for the column PropertyInfo p = item.GetType().GetProperty(c.ColumnName); // if exists, set the value if (p != null && row[c] != DBNull.Value) { try { p.SetValue(item, row[c], null); } catch { // swallow??? } } } } } public static class DbContextExtensions { /// /// /// /// /// /// /// /// /// List results = DynamicListFromSql(myDb, /// "select * from table where a=@a and b=@b", /// new Dictionary { { "a", true }, { "b", false } }) /// .ToList(); /// public static IEnumerable DynamicListFromSql(this DbContext db, string Sql, Dictionary Params) { using (var cmd = db.Database.Connection.CreateCommand()) { cmd.CommandText = Sql; if (cmd.Connection.State != ConnectionState.Open) { cmd.Connection.Open(); } foreach (KeyValuePair p in Params) { DbParameter dbParameter = cmd.CreateParameter(); dbParameter.ParameterName = p.Key; dbParameter.Value = p.Value; cmd.Parameters.Add(dbParameter); } using (var dataReader = cmd.ExecuteReader()) { while (dataReader.Read()) { var row = new ExpandoObject() as IDictionary; for (var fieldCount = 0; fieldCount < dataReader.FieldCount; fieldCount++) { if (!row.ContainsKey(dataReader.GetName(fieldCount))) { row.Add(dataReader.GetName(fieldCount), dataReader[fieldCount]); } } yield return row; } } } } } public static class EntityExtensions { public static decimal? CalculateSellingPrice(this QuoteItem quoteItem, decimal? newMargin = null) { decimal margin = newMargin ?? quoteItem.Margin.GetValueOrDefault(); quoteItem.SellingPrice = BusinessUtils.GetSellingPrice( costPrice: quoteItem.CostPrice, newMargin: margin); return quoteItem.SellingPrice; } public static decimal? CalculateSellingPrice(this oQuoteItems quoteItem, decimal? newMargin = null) { decimal margin = newMargin ?? quoteItem.QuoteItems_QuoteItems_QuoteItemsMargin; quoteItem.QuoteItems_QuoteItems_QuoteItemsSellingPrice = BusinessUtils.GetSellingPrice( costPrice: quoteItem.QuoteItems_QuoteItems_QuoteItemsCostPrice, newMargin: margin); return quoteItem.QuoteItems_QuoteItems_QuoteItemsSellingPrice; } } public static class MappingExtensions { public static TTarget MapTo(this TSource source) { var target = (TTarget)Activator.CreateInstance(typeof(TTarget)); var targetProperties = typeof(TTarget).GetProperties(BindingFlags.Public | BindingFlags.Instance); var sourceProperties = typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var targetProp in targetProperties) { var sourceProp = sourceProperties.FirstOrDefault(p => p.Name.Equals(targetProp.Name)); if (sourceProp.IsNotNull()) { if (targetProp.PropertyType.Equals(typeof(string))) { var sourceValue = sourceProp.GetValue(source, null); targetProp.SetValue(target, sourceValue?.ToString() ?? string.Empty); } else //if (Nullable.GetUnderlyingType(sourceProp.PropertyType).IsNotNull()) { //var uType = Nullable.GetUnderlyingType(sourceProp.PropertyType); var sourceValue = sourceProp.GetValue(source); if (sourceValue.IsNull()) { targetProp.SetValue(target, Activator.CreateInstance(targetProp.PropertyType)); } else { targetProp.SetValue(target, sourceValue); } } } } return target; } public static TTarget Inject(this TTarget target, object source) { var targetProperties = target.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); var sourceProperties = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var sourceProp in sourceProperties) { var targetProp = targetProperties.FirstOrDefault(p => p.Name.Equals(sourceProp.Name)); if (targetProp.IsNotNull()) { if (sourceProp.PropertyType == targetProp.PropertyType) { var sourceValue = sourceProp.GetValue(source, null); targetProp.SetValue(target, sourceValue); } else { var sourceValue = sourceProp.GetValue(source); if (sourceValue.IsNull()) { targetProp.SetValue(target, Activator.CreateInstance(targetProp.PropertyType)); } else { targetProp.SetValue(target, sourceValue); } } } } return target; } } public static class ValidationExtensions { public static bool IsValidEmail(this string email) => email.IsNotEmpty() && new EmailAddressAttribute().IsValid(email); } }