-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
38 changed files
with
2,336 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netcoreapp2.1</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.4.0" /> | ||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.1" /> | ||
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="2.1.1" /> | ||
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.5.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Reference Include="AA.FrameWork"> | ||
<HintPath>..\AA.FrameWork\bin\Debug\netstandard2.0\AA.FrameWork.dll</HintPath> | ||
</Reference> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,362 @@ | ||
using AA.AspNetCore.Infrastructure; | ||
using AA.FrameWork; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.ComponentModel; | ||
using System.Globalization; | ||
using System.Linq; | ||
using System.Net; | ||
using System.Reflection; | ||
using System.Security.Cryptography; | ||
using System.Text.RegularExpressions; | ||
namespace AA.AspNetCore | ||
{ | ||
/// <summary> | ||
/// Represents a common helper | ||
/// </summary> | ||
public partial class CommonHelper | ||
{ | ||
#region Fields | ||
|
||
//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])))$"; | ||
|
||
private static readonly Regex _emailRegex; | ||
|
||
#endregion | ||
|
||
#region Ctor | ||
|
||
static CommonHelper() | ||
{ | ||
_emailRegex = new Regex(_emailExpression, RegexOptions.IgnoreCase); | ||
} | ||
|
||
#endregion | ||
|
||
#region Methods | ||
|
||
/// <summary> | ||
/// Ensures the subscriber email or throw. | ||
/// </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 Exception("Email is not valid."); | ||
} | ||
|
||
return output; | ||
} | ||
|
||
/// <summary> | ||
/// Verifies that a string is in valid e-mail format | ||
/// </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); | ||
} | ||
|
||
/// <summary> | ||
/// Verifies that string is an valid IP-Address | ||
/// </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 _); | ||
} | ||
|
||
/// <summary> | ||
/// Generate random digit code | ||
/// </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; | ||
} | ||
|
||
/// <summary> | ||
/// Returns an random integer number within a specified rage | ||
/// </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); | ||
} | ||
|
||
/// <summary> | ||
/// Ensure that a string doesn't exceed maximum allowed length | ||
/// </summary> | ||
/// <param name="str">Input string</param> | ||
/// <param name="maxLength">Maximum length</param> | ||
/// <param name="postfix">A string to add to the end if the original string was shorten</param> | ||
/// <returns>Input string if its length is OK; otherwise, truncated input string</returns> | ||
public static string EnsureMaximumLength(string str, int maxLength, string postfix = null) | ||
{ | ||
if (string.IsNullOrEmpty(str)) | ||
return str; | ||
|
||
if (str.Length <= maxLength) | ||
return str; | ||
|
||
var pLen = postfix?.Length ?? 0; | ||
|
||
var result = str.Substring(0, maxLength - pLen); | ||
if (!string.IsNullOrEmpty(postfix)) | ||
{ | ||
result += postfix; | ||
} | ||
|
||
return result; | ||
} | ||
|
||
/// <summary> | ||
/// Ensures that a string only contains numeric values | ||
/// </summary> | ||
/// <param name="str">Input string</param> | ||
/// <returns>Input string with only numeric values, empty string if input is null/empty</returns> | ||
public static string EnsureNumericOnly(string str) | ||
{ | ||
return string.IsNullOrEmpty(str) ? string.Empty : new string(str.Where(char.IsDigit).ToArray()); | ||
} | ||
|
||
/// <summary> | ||
/// Ensure that a string is not null | ||
/// </summary> | ||
/// <param name="str">Input string</param> | ||
/// <returns>Result</returns> | ||
public static string EnsureNotNull(string str) | ||
{ | ||
return str ?? string.Empty; | ||
} | ||
|
||
/// <summary> | ||
/// Indicates whether the specified strings are null or empty strings | ||
/// </summary> | ||
/// <param name="stringsToValidate">Array of strings to validate</param> | ||
/// <returns>Boolean</returns> | ||
public static bool AreNullOrEmpty(params string[] stringsToValidate) | ||
{ | ||
return stringsToValidate.Any(string.IsNullOrEmpty); | ||
} | ||
|
||
/// <summary> | ||
/// Compare two arrays | ||
/// </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; | ||
return !a1.Where((t, i) => !comparer.Equals(t, a2[i])).Any(); | ||
} | ||
|
||
/// <summary> | ||
/// Sets a property on an object to a value. | ||
/// </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 AAException("No property '{0}' found on the instance of type '{1}'.", propertyName, instanceType); | ||
if (!pi.CanWrite) | ||
throw new AAException("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]); | ||
} | ||
|
||
/// <summary> | ||
/// Converts a value to a destination type. | ||
/// </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> | ||
/// Converts a value to a destination type. | ||
/// </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) | ||
return null; | ||
|
||
var sourceType = value.GetType(); | ||
|
||
var destinationConverter = TypeDescriptor.GetConverter(destinationType); | ||
if (destinationConverter.CanConvertFrom(value.GetType())) | ||
return destinationConverter.ConvertFrom(null, culture, value); | ||
|
||
var sourceConverter = TypeDescriptor.GetConverter(sourceType); | ||
if (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> | ||
/// Converts a value to a destination type. | ||
/// </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)); | ||
} | ||
|
||
/// <summary> | ||
/// Convert enum for front-end | ||
/// </summary> | ||
/// <param name="str">Input string</param> | ||
/// <returns>Converted string</returns> | ||
public static string ConvertEnum(string str) | ||
{ | ||
if (string.IsNullOrEmpty(str)) return string.Empty; | ||
var result = string.Empty; | ||
foreach (var c in str) | ||
if (c.ToString() != c.ToString().ToLower()) | ||
result += " " + c.ToString(); | ||
else | ||
result += c.ToString(); | ||
|
||
//ensure no spaces (e.g. when the first letter is upper case) | ||
result = result.TrimStart(); | ||
return result; | ||
} | ||
|
||
/// <summary> | ||
/// Set Telerik (Kendo UI) culture | ||
/// </summary> | ||
public static void SetTelerikCulture() | ||
{ | ||
//little hack here | ||
//always set culture to 'en-US' (Kendo UI has a bug related to editing decimal values in other cultures) | ||
var culture = new CultureInfo("en-US"); | ||
CultureInfo.CurrentCulture = culture; | ||
CultureInfo.CurrentUICulture = culture; | ||
} | ||
|
||
/// <summary> | ||
/// Get difference in years | ||
/// </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; | ||
} | ||
|
||
/// <summary> | ||
/// Get private fields property value | ||
/// </summary> | ||
/// <param name="target">Target object</param> | ||
/// <param name="fieldName">Field name</param> | ||
/// <returns>Value</returns> | ||
public static object GetPrivateFieldValue(object target, string fieldName) | ||
{ | ||
if (target == null) | ||
{ | ||
throw new ArgumentNullException("target", "The assignment target cannot be null."); | ||
} | ||
|
||
if (string.IsNullOrEmpty(fieldName)) | ||
{ | ||
throw new ArgumentException("fieldName", "The field name cannot be null or empty."); | ||
} | ||
|
||
var t = target.GetType(); | ||
FieldInfo fi = null; | ||
|
||
while (t != null) | ||
{ | ||
fi = t.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic); | ||
|
||
if (fi != null) break; | ||
|
||
t = t.BaseType; | ||
} | ||
|
||
if (fi == null) | ||
{ | ||
throw new Exception($"Field '{fieldName}' not found in type hierarchy."); | ||
} | ||
|
||
return fi.GetValue(target); | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
|
||
/// <summary> | ||
/// Gets or sets the default file provider | ||
/// </summary> | ||
public static IAAFileProvider DefaultFileProvider { get; set; } | ||
|
||
#endregion | ||
} | ||
} |
Oops, something went wrong.