Vega
Helper.cs
/*
Description: Vega - Fastest ORM with enterprise features
Author: Ritesh Sutaria
Date: 9-Dec-2017
Home Page: https://github.com/aadreja/vega
http://www.vegaorm.com
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Text;
namespace Vega
{
///
/// Vega extension and helper methods
///
public static clast Helper
{
#region constructor
static Helper()
{
mTypeHash = new Hashtable
{
[typeof(sbyte)] = OpCodes.Ldind_I1,
[typeof(byte)] = OpCodes.Ldind_U1,
[typeof(char)] = OpCodes.Ldind_U2,
[typeof(short)] = OpCodes.Ldind_I2,
[typeof(ushort)] = OpCodes.Ldind_U2,
[typeof(int)] = OpCodes.Ldind_I4,
[typeof(uint)] = OpCodes.Ldind_U4,
[typeof(long)] = OpCodes.Ldind_I8,
[typeof(ulong)] = OpCodes.Ldind_I8,
[typeof(bool)] = OpCodes.Ldind_I1,
[typeof(double)] = OpCodes.Ldind_R8,
[typeof(float)] = OpCodes.Ldind_R4
};
}
#endregion
#region type extension
#region idbcommand extension
///
/// Adds out parameter to the command
///
/// IDbCommand object
/// Name of parameter
/// DbType of parameter
public static void AddOutParameter(this IDbCommand cmd,
string name,
DbType dbType)
{
AddParameter(cmd, name, dbType, ParameterDirection.Output, name, DataRowVersion.Default, null);
}
///
/// Adds In parameter to the command
///
/// IDbCommand object
/// Name of parameter
/// DbType of parameter
/// Value of parameter
public static void AddInParameter(this IDbCommand cmd,
string name,
DbType dbType,
object value)
{
AddParameter(cmd, name, dbType, ParameterDirection.Input, String.Empty, DataRowVersion.Default, value);
}
///
/// Adds Parameter to the command
///
/// IDbCommand object
/// Name of parameter
/// DbType of parameter
/// Director: In or Out
/// Name of the source column for loading or returning the System.Data.IDataParameter.Value.
/// System.Data.DataRowVersion to use when loading System.Data.IDataParameter.Value
/// Value of parameter
public static void AddParameter(this IDbCommand cmd,
string name,
DbType dbType,
ParameterDirection direction,
string sourceColumn,
DataRowVersion sourceVersion,
object value)
{
AddParameter(cmd, name, dbType, 0, direction, false, 0, 0, sourceColumn, sourceVersion, value);
}
///
/// Adds Parameter to the command
///
/// IDbCommand object
/// Name of parameter
/// DbType of parameter
/// Director: In or Out
/// Name of the source column for loading or returning the System.Data.IDataParameter.Value.
/// System.Data.DataRowVersion to use when loading System.Data.IDataParameter.Value
/// Size of column
/// Is Null values allowed
/// For Numeric data size e.g. Decimal(10)
/// For Numeric data scale size e.g. Decimal(10,2)
/// Value of parameter
public static void AddParameter(this IDbCommand cmd,
string name,
DbType dbType,
int size,
ParameterDirection direction,
bool nullable,
byte precision,
byte scale,
string sourceColumn,
DataRowVersion sourceVersion,
object value)
{
if (cmd == null) throw new ArgumentNullException("command");
IDbDataParameter parameter = cmd.CreateParameter();
parameter.ParameterName = name;
parameter.DbType = dbType;
parameter.Size = size;
parameter.Direction = direction;
//parameter.IsNullable = nullable; //TODO
parameter.Precision = precision;
parameter.Scale = scale;
parameter.SourceColumn = sourceColumn;
parameter.SourceVersion = sourceVersion;
parameter.Value = value.ToParameterValue();
cmd.Parameters.Add(parameter);
}
#endregion
#region object extension
///
/// Box Parameter Value to type as per database
///
/// object of value
/// boxed value
internal static object ToParameterValue(this object value)
{
if (value == null)
{
return DBNull.Value;
}
//TODO: not all needs mindatetime to be stored as null
//if (value is DateTime && (DateTime)value == DateTime.MinValue) return DBNull.Value;
if (value is Guid) if (Equals(value, Guid.Empty)) return DBNull.Value; else return value;
else if (value.GetType().IsEnum) return Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()));
else return value;
}
///
/// Change escaped characters in XML and retuns XML format string
///
/// Value to convert
/// dbtype of column
/// xml string
internal static string ToXMLValue(this object value, DbType dbType)
{
if (value == null) return string.Empty;
string strValue = (dbType == DbType.DateTime ||
dbType == DbType.Date) ? strValue = ((DateTime)value).ToSQLDateTime() : value.ToString();
//replace special characters in XML //" ' & < >
strValue = strValue.Replace("'", "'").Replace("\"", """).Replace("&", "&").Replace("", ">");
return strValue;
}
///
/// Checks whether value is number returns true if number else false
///
/// any object
/// true or false
public static bool IsNumber(this object value)
{
return value is sbyte
|| value is byte
|| value is short
|| value is ushort
|| value is int
|| value is uint
|| value is long
|| value is ulong
|| value is float
|| value is double
|| value is decimal;
}
///
/// Checks whether value is of AnonymousType
///
/// any object
/// true or false
public static bool IsAnonymousType(this object value)
{
if (value == null)
return false;
Type type = value.GetType();
return Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false)
&& type.IsGenericType && type.Name.Contains("AnonymousType")
&& (type.Name.StartsWith("", StringComparison.OrdinalIgnoreCase) ||
type.Name.StartsWith("VB$", StringComparison.OrdinalIgnoreCase))
&& (type.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic;
}
#endregion
#region datetime extension
///
/// From SQL format datetime (yyyy-MM-dd) to datetime
///
/// String date
///
public static DateTime FromSQLDateTime(this string pDate)
{
DateTime.TryParse(pDate, out DateTime result);
return result;
}
///
/// To SQL format datetime (yyyy-MM-dd HH:mm:ss)
///
/// DateTime
///
public static string ToSQLDateTime(this DateTime pDate)
{
return pDate.ToString("yyyy-MM-dd HH:mm:ss");
}
///
/// To SQL format datetime (yyyy-MM-dd HH:mm:ss)
///
/// DateTime Nullable
///
public static string ToSQLDateTime(this DateTime? pDate)
{
if (pDate == null) return string.Empty;
else return ToSQLDateTime((DateTime)pDate);
}
///
/// From SQL format datetime (yyyy-MM-dd) to datetime
///
/// String date
///
public static DateTime FromSQLDate(this string pDate)
{
DateTime.TryParse(pDate, out DateTime result);
return result;
}
///
/// To SQL format date (yyyy-MM-dd)
///
/// DateTime
///
public static string ToSQLDate(this DateTime pDate)
{
return pDate.ToString("yyyy-MM-dd");
}
///
/// To SQL format date (yyyy-MM-dd)
///
/// Nullable DateTime
///
public static string ToSQLDate(this DateTime? pDate)
{
if (pDate == null) return string.Empty;
else return ToSQLDate((DateTime)pDate);
}
#endregion
#region string & stringbuilder extension
internal static string RemoveLastComma(this string pString)
{
if (pString[pString.Length - 1] == ',')
{
pString = pString.Remove(pString.Length - 1, 1);
}
return pString;
}
internal static StringBuilder RemoveLastComma(this StringBuilder pString)
{
if (pString[pString.Length - 1] == ',')
{
pString.Remove(pString.Length - 1, 1);
}
return pString;
}
#endregion
#endregion
#region converters
internal static R Parse(this object value)
{
if (value == null || value is DBNull) return default(R);
if (value is R) return (R)value;
Type type = typeof(R);
if (type.IsEnum)
{
value = Convert.ChangeType(value, Enum.GetUnderlyingType(type), CultureInfo.InvariantCulture);
return (R)Enum.ToObject(type, value);
}
else
{
return (R)Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
}
}
internal static object ConvertTo(this object value, Type type)
{
var converter = TypeDescriptor.GetConverter(type);
return converter.ConvertFrom(value);
}
internal static object ConvertTo(this string value, Type type)
{
var converter = TypeDescriptor.GetConverter(type);
return converter.ConvertFromString(value);
}
internal static object GetDateTimeOrDatabaseDateTimeSQL(DateTime? dateTime, Database db, bool overRideCreatedUpdatedOn)
{
if(!overRideCreatedUpdatedOn || dateTime == null || dateTime == default(DateTime))
return db.CURRENTDATETIMESQL;
else
return dateTime;
}
#endregion
#region Configuration Helper Methods
/////
///// Reads value from AppSettings sections from App.Config or Web.Config file
/////
///// String value indicating Key.
///// if found returns value of the specified key from the .config files, otherwise returns Empty string.
//public static string GetAppSetting(String pKey)
//{
// if (ConfigurationManager.AppSettings[pKey] != null)
// return ConfigurationManager.AppSettings[pKey].ToString();
// else
// return string.Empty;
//}
/////
///// Reads value from ConnectionStrings sections from App.Config or Web.Config file
/////
///// String value indicating Key.
///// if found returns value of the specified key from the .config files, otherwise returns Empty string.
//public static string GetConnectionString(String pKey)
//{
// if (ConfigurationManager.ConnectionStrings[pKey] != null)
// return ConfigurationManager.ConnectionStrings[pKey].ToString();
// else
// return string.Empty;
//}
#endregion
#region Emit Helper
//https://www.codeproject.com/Articles/9927/Fast-Dynamic-Property-Access-with-C
static Hashtable mTypeHash;
internal static Func CreateGetProperty(Type ensatyType, string propertyName)
{
MethodInfo mi = ensatyType.GetProperty(propertyName).GetMethod;
if (mi == null) return null; //no get property
Type[] args = new Type[] { typeof(object) };
DynamicMethod method = new DynamicMethod("Get_" + ensatyType.Name + "_" + propertyName, typeof(object), args, ensatyType.Module, true);
ILGenerator getIL = method.GetILGenerator();
getIL.DeclareLocal(typeof(object));
getIL.Emit(OpCodes.Ldarg_0); //Load the first argument
//(target object)
//Cast to the source type
getIL.Emit(OpCodes.Castclast, ensatyType);
//Get the property value
getIL.EmitCall(OpCodes.Call, mi, null);
if (mi.ReturnType.IsValueType)
{
getIL.Emit(OpCodes.Box, mi.ReturnType);
//Box if necessary
}
getIL.Emit(OpCodes.Stloc_0); //Store it
getIL.Emit(OpCodes.Ldloc_0);
getIL.Emit(OpCodes.Ret);
var funcType = System.Linq.Expressions.Expression.GetFuncType(typeof(object), typeof(object));
return (Func)method.CreateDelegate(funcType);
}
internal static Action CreateSetProperty(Type ensatyType, string propertyName)
{
MethodInfo mi = ensatyType.GetProperty(propertyName).SetMethod;
if (mi == null) return null; //no set property
Type[] args = new Type[] { typeof(object), typeof(object) };
DynamicMethod method = new DynamicMethod("Set_" + ensatyType.Name + "_" + propertyName, null, args, ensatyType.Module, true);
ILGenerator setIL = method.GetILGenerator();
Type paramType = mi.GetParameters()[0].ParameterType;
//setIL.DeclareLocal(typeof(object));
setIL.Emit(OpCodes.Ldarg_0); //Load the first argument [Ensaty]
//(target object)
//Cast to the source type
setIL.Emit(OpCodes.Castclast, ensatyType);
setIL.Emit(OpCodes.Ldarg_1); //Load the second argument [Value]
//(value object)
if (paramType.IsValueType)
{
setIL.Emit(OpCodes.Unbox, paramType); //Unbox it
if (mTypeHash[paramType] != null) //and load
{
OpCode load = (OpCode)mTypeHash[paramType];
setIL.Emit(load);
}
else
{
setIL.Emit(OpCodes.Ldobj, paramType);
}
}
else
{
setIL.Emit(OpCodes.Castclast, paramType); //Cast clast
}
setIL.EmitCall(OpCodes.Callvirt, mi, null); //Set the property value
setIL.Emit(OpCodes.Ret);
var actionType = System.Linq.Expressions.Expression.GetActionType(typeof(object), typeof(object));
return (Action)method.CreateDelegate(actionType);
}
#endregion
}
}