using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; using Kreta.Core.CustomAttributes; namespace Kreta.Core { /// <summary> /// Extension /// </summary> public static class Extensions { #region Convert Extensions /// <summary> /// Converts to a bool? value to int /// </summary> /// <param name="origin">The origin.</param> /// <returns></returns> public static int ToNullableInt(this bool? origin) => origin == true ? 1 : 0; /// <summary> /// Converts to a bool value to int /// </summary> /// <param name="origin">if set to <c>true</c> [origin].</param> /// <returns></returns> public static int ToNullableInt(this bool origin) => origin ? 1 : 0; /// <summary> /// Converts to a bool? value to int /// </summary> /// <param name="origin">The origin.</param> /// <returns></returns> public static int ToBit(this bool? origin) => origin.ToNullableInt(); /// <summary> /// Converts to a bool value to int /// </summary> /// <param name="origin">if set to <c>true</c> [origin].</param> /// <returns></returns> public static int ToBit(this bool origin) => origin.ToNullableInt(); /// <summary> /// Converts to a int? value to bool /// </summary> /// <param name="origin">The origin.</param> /// <returns></returns> public static bool ToBool(this int? origin) => origin == 1; /// <summary> /// Converts to a string value to bool /// </summary> /// <param name="origin">The origin.</param> /// <returns></returns> public static bool ToBool(this string origin) => string.Equals(origin, "T", StringComparison.OrdinalIgnoreCase) || string.Equals(origin, "TRUE", StringComparison.OrdinalIgnoreCase); /// <summary> /// Determines whether [is not null and positive] [the specified value]. /// </summary> /// <param name="value">The value.</param> /// <returns></returns> public static bool IsNotNullAndPositive(this int? value) { return value.HasValue && 0 < value; } /// <summary> /// Determines whether [is not null and positive] [the specified value]. /// </summary> /// <param name="value">The value.</param> /// <returns></returns> public static bool IsNotNullAndPositive(this int value) { return 0 < value; } /// <summary> /// Megvizsgálja, hogy az int? lehetséges EntityId-e (nem null és nagyobb mint 0) /// </summary> /// <param name="value">The value.</param> /// <returns></returns> public static bool IsEntityId(this int? value) { return value.IsNotNullAndPositive(); } /// <summary> /// Megvizsgálja, hogy az int lehetséges EntityId-e (nagyobb mint 0) /// </summary> /// <param name="value">The value.</param> /// <returns></returns> public static bool IsEntityId(this int value) { return 0 < value; } public static int? ToNullableInt(this string stringValue) { if (int.TryParse(stringValue, out int intValue)) { return intValue; } return null; } /// <summary> /// Converts to a bool? value to bool /// </summary> /// <param name="value">The origin.</param> /// <returns>False when it is null</returns> public static bool ToBool(this bool? value) { return value ?? false; } public static string ToSDABoolean(this bool value) => value ? "T" : "F"; public static bool? ToNullableBoolean(this int? value) => value.HasValue ? (value.Value == 1) : (bool?)null; #endregion #region Validation Extensions public static bool IsValidEmail(this string value) { //NOTE: A null-t és az üres string-et is validnak vesszük, ha azt szeretnénk, hogy ezek ne legyenek validok, azokat külön kint kell vizsgálni string.IsNullOrWhiteSpace()-vel! bool result = new EmailAddressExtendedAttribute(true, true).IsValid(value); return result; } public static bool IsValidPhone(this string value) { //NOTE: A null-t és az üres string-et is validnak vesszük, ha azt szeretnénk, hogy ezek ne legyenek validok, azokat külön kint kell vizsgálni string.IsNullOrWhiteSpace()-vel! bool result = new PhoneExtendedAttribute(true, true).IsValid(value); return result; } public static bool Is18EvesElmult(this DateTime szuletesiIdo) { bool result = szuletesiIdo.Date.AddYears(18) < DateTime.Today; return result; } #endregion #region String Extensions public static string Truncate(this string value, int maxChars) { return value.Length <= maxChars ? value : value.Substring(0, maxChars - 3) + "..."; } public static string RemoveDiacritics(this string text) { if (string.IsNullOrWhiteSpace(text)) { return text; } text = text.Normalize(NormalizationForm.FormD); var chars = text .Where(c => CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) .ToArray(); return new string(chars).Normalize(NormalizationForm.FormC); } public static string ReplaceMultipleSpacesAndTrim(this string text, string defaultValue = null) { if (string.IsNullOrWhiteSpace(text)) { return defaultValue; } //NOTE: "\u00A0" = NO-BREAK SPACE // "\u0009" = CHARACTER TABULATION // "\u0020" = SPACE // Replace-elni kell a NO-BREAK SPACE-eket, mert a SPACE-el nem ekvivalens és jöhet be ilyen adat és okozhat problémát. // Replace-elni kell a CHARACTER TABULATION-öket, mert a SPACE-el nem ekvivalens és jöhet be ilyen adat és okozhat problémát. // Ezt követően replace-eljük a többszörös szóközöket egyre. // Ezt követően trim-elünk. string result = Regex.Replace(text.Replace("\u00A0", "\u0020").Replace("\u0009", "\u0020"), @"\s+", " ").Trim(); if (string.IsNullOrWhiteSpace(result)) { return defaultValue; } return result; } public static string RemoveSpecialCharacters(this string text) => Regex.Replace(text, @"[ \-'`~!@#$%^&*()_|+=?;:"",.<>{ }[\]\\/]", ""); #endregion #region Collection Extensions public static int GetSequenceHashCode<T>(this IReadOnlyCollection<T> sequence) { if (sequence == null || sequence.Count == 0) { return 0; } return sequence.Select(item => item.GetHashCode()).Aggregate((total, nextCode) => total ^ nextCode); } public static void RemoveRange<T>(this List<T> self, IEnumerable<T> items) { var exceptItems = self.Except(items).ToList(); self.Clear(); self.AddRange(exceptItems); } public static bool NotNullAndAny<T>(this IEnumerable<T> enumerable) { return enumerable != null && enumerable.Any(); } /// <summary> /// A generikus objektumlistában sorba rendezzük az adatokat és beállítjuk a lapozást a bejövő paraméterek alapján reflection-el. /// </summary> /// <typeparam name="T">A T bármilyen típus lehet.</typeparam> /// <param name="itemList">A T típusú objektumlista, amivel dolgozunk. Ha ez az érték null, akkor null-al térünk vissza, hogy ne legyen exception.</param> /// <param name="orderDictionary">A dictionary, amiben benne van, hogy mely property-k(Key) alapján és milyen irányba(Value) kell rendezni az adatokat. Ha ez az érték null vagy üres, akkor nincs sorbarendezés, hanem az eredeti sorrenddel dolgozunk tovább.</param> /// <param name="firstItemIndex">A lapozáshoz az első elem indexe. Ha ez az érték null, akkor nincs lapozás és visszaadunk minden elemet.</param> /// <param name="lastItemIndex">A lapozáshoz az utolsó elem indexe. Ha ez az érték null, akkor nincs lapozás és visszaadunk minden elemet.</param> /// <returns></returns> public static List<T> SortingAndPaging<T>(this IEnumerable<T> itemList, Dictionary<string, ListSortDirection> orderDictionary = null, int? firstItemIndex = null, int? lastItemIndex = null) { if (itemList == null) { return null; } List<T> result; if (orderDictionary != null && orderDictionary.Count > 0) { IOrderedEnumerable<T> orderedList = null; bool isOrderBy = true; foreach (var orderItem in orderDictionary) { PropertyInfo propInfo = typeof(T).GetProperty(orderItem.Key); if (isOrderBy) { orderedList = orderItem.Value == ListSortDirection.Ascending ? itemList.OrderBy(x => propInfo.GetValue(x, null)) : itemList.OrderByDescending(x => propInfo.GetValue(x, null)); isOrderBy = false; } else { orderedList = orderItem.Value == ListSortDirection.Ascending ? orderedList.ThenBy(x => propInfo.GetValue(x, null)) : orderedList.ThenByDescending(x => propInfo.GetValue(x, null)); } } result = orderedList.ToList(); } else { result = itemList.ToList(); } if (firstItemIndex.HasValue && lastItemIndex.HasValue) { if (firstItemIndex <= lastItemIndex) { int pageSize = lastItemIndex.Value - firstItemIndex.Value + 1; if (pageSize < result.Count) { result = result.Skip(firstItemIndex.Value).Take(pageSize).ToList(); } } } return result; } public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) { var keys = new HashSet<TKey>(); foreach (TSource element in source) { if (keys.Add(keySelector(element))) { yield return element; } } } public static IEnumerable<T> Difference<T>(this IEnumerable<T> first, IEnumerable<T> second) { return first.Except(second).Union(second.Except(first)); } public static void RemoveDictionaryItemByValue(this Dictionary<string, string> self, string value) { var valuesList = self.Where(s => s.Value == value).ToList(); valuesList.ForEach(i => self.Remove(i.Key)); } #endregion #region Enumeration Extensions /// <summary> /// GetAttribute by Type /// </summary> /// <typeparam name="T">type of attribute</typeparam> /// <returns>type of Attribute</returns> public static T GetAttribute<T>(this System.Enum value) where T : Attribute { return (T)value.GetType() .GetMember(value.ToString())[0].GetCustomAttributes(typeof(T), false) .FirstOrDefault(); } /// <summary> ///Get Display Name Attribute /// </summary> /// <example> [Display(Name = "xy")]</example> /// <returns>xy</returns> public static string ToDisplayName(this System.Enum value) => value.GetAttribute<DisplayAttribute>()?.Name; #endregion #region DateTimeExtensions public static DateTime StartOfTheDay(this DateTime dateTime) { return dateTime.Date; } public static DateTime EndOfTheDay(this DateTime dateTime) { return dateTime.Date.AddDays(1).AddTicks(-1); } #endregion DateTimeExtensions } }