using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace xCommons.Extensions
{
public static partial class ModelExtensions
{
///
/// Retrieve a Binding Flag for Retrieve all Instance Members including
/// Priate and Public ...
///
///
public static BindingFlags GetDefaultBindingFlag()
{
return BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
}
///
/// Update an Instance of a Typed Object with Data Provided by another Instance of Typed Object
///
///
///
///
///
///
///
///
///
///
///
public static T UpdateData(
this T source,
D updateWith,
ICollection propertyWhiteList = null,
ICollection propertyBlackList = null,
ICollection>> propertyValueProviders = null,
bool updateWithNullOrEmptyValues = false,
bool throwExceptionOnFails = false
)
where T : class
where D : class
{
//
var hasWhiteList = propertyWhiteList.HasChild();
var hasBlackList = propertyBlackList.HasChild();
var hasValueProvider = propertyValueProviders.HasChild>>();
//
var fullPropertyList = updateWith.GetType().GetProperties().Select(prop => prop.Name);
var mustSetProps = (hasWhiteList ? propertyWhiteList : fullPropertyList);
//
if (hasBlackList)
{
mustSetProps = mustSetProps.Where(propName => !propertyBlackList.Contains(propName));
}
//
mustSetProps.ToList().ForEach(propName =>
{
//
try
{
//
var sourceProp = source.GetType().GetProperty(propName);
var sourceValue = sourceProp.GetValue(source);
var sourceValueType = sourceValue.IsNull() ? null : sourceValue.GetType();
//
var updateWithProp = updateWith.GetType().GetProperty(propName);
var updateWithValue = updateWithProp.GetValue(updateWith);
var updateWithValueType = updateWithValue.IsNull() ? null : updateWithValue.GetType();
//
var valueProviderValue = hasValueProvider ? propertyValueProviders
.FirstOrDefault(p => p.Key == propName).Value : null;
var updateVal = !valueProviderValue.IsNull() ?
valueProviderValue.Invoke(updateWith) :
(updateWithValue.IsNull() && !updateWithNullOrEmptyValues) ?
sourceValue : updateWithValue;
var updateValType = updateVal.IsNull() ? null : updateVal.GetType();
//
Type t = Nullable.GetUnderlyingType(sourceProp.PropertyType) ?? sourceProp.PropertyType;
object safeValue =
(updateVal == null) ?
null :
!updateValType.IsCollectionType() ?
Convert.ChangeType(updateVal, t) :
updateVal;
//
sourceProp.SetValue(source, safeValue);
}
catch (Exception ex)
{
//
if (throwExceptionOnFails)
{
throw ex;
}
}
});
//
return source;
}
///
/// Check a Class is Contains a Property or not ...
///
///
///
///
///
///
public static bool HasProperty(
this T source,
string property,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
where T : class
{
//
var result = source
.GetType()
.GetProperties(bindingAttr)
.Any(prop => prop.Name == property); ;
//
return result;
}
///
/// Check a Class is Contains a field or not ...
///
///
///
///
///
///
public static bool HasField(
this T source,
string field,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
where T : class
{
//
var result = source
.GetType()
.GetFields(bindingAttr)
.Any(fld => fld.Name == field);
//
return result;
}
///
/// Check a Class is Contains a Method or not ...
///
///
///
///
///
///
public static bool HasMethod(
this T source,
string method,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
where T : class
{
//
var result = source
.GetType()
.GetMethods(bindingAttr)
.Any(mthd => mthd.Name == method);
//
return result;
}
///
/// Retrieve a Class Properties Names ...
///
///
///
///
///
public static string[] GetPropertiesNames(
this T source,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
{
//
var result = source
.GetType()
.GetProperties(bindingAttr)
.Select(p => p.Name)
.ToArray();
//
return result;
}
///
/// Retrieve a Class Fields Names ...
///
///
///
///
///
public static string[] GetFieldsNames(
this T source,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
{
//
var result = source
.GetType()
.GetFields(bindingAttr)
.Select(p => p.Name)
.ToArray();
//
return result;
}
///
/// Retrieve a Class Methods Names ...
///
///
///
///
///
public static string[] GetMethodsNames(
this T source,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
{
//
var result = source
.GetType()
.GetMethods(bindingAttr)
.Select(p => p.Name)
.ToArray();
//
return result;
}
///
/// Retrieve a Class Members Names ...
///
///
///
///
///
public static string[] GetMembersNames(
this T source,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
{
//
var result = source
.GetType()
.GetMembers(bindingAttr)
.Select(p => p.Name)
.ToArray();
//
return result;
}
///
/// Get a Class Property Value using Generic Concept ...
///
///
///
///
///
///
///
public static TProp GetProperty(
this T source,
string property,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
where T : class
{
//
TProp result = default;
//
// Check if T Has Property ...
if (source.HasProperty(property))
{
//
// Access Property ...
var prop = source
.GetType()
.GetProperty(
property,
bindingAttr
);
//
// Retrieve Property Value as Object ...
var propVal = prop.GetValue(source);
//
result = (TProp)propVal;
}
//
return result;
}
///
/// Get a Class Field Value using Generic Concept ...
///
///
///
///
///
///
///
public static TField GetField(
this T source,
string field,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
where T : class
{
//
TField result = default;
//
if (source.HasField(field))
{
//
var fld = source
.GetType()
.GetField(
field,
bindingAttr
);
//
var fieldVal = fld.GetValue(source);
result = (TField)fieldVal;
}
//
return result;
}
///
/// Set a Class Property Value using Generic Concept ...
///
///
///
///
///
///
///
///
public static bool SetProperty(
this T source,
string property,
TProp value,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
where T : class
{
//
// Check T Has Property ...
var result = source.HasProperty(property);
if (!result)
{
return result;
}
//
// Access Property ...
var prop = source
.GetType()
.GetProperty(
property,
bindingAttr
);
//
// Set Property ...
try
{
//
result = true;
prop.SetValue(source, value);
}
catch
{
result = false;
}
//
return result;
}
///
/// Set a Class Field Value using Generic Concept ...
///
///
///
///
///
///
///
///
public static bool SetField(
this T source,
string field,
TField value,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
where T : class
{
//
// Check T Has Field ...
var result = source.HasField(field);
if (!result)
{
return result;
}
//
// Access Field ...
var fld = source
.GetType()
.GetField(
field,
bindingAttr
);
//
// Set Value ...
try
{
//
result = true;
fld.SetValue(source, value);
}
catch
{
result = false;
}
//
return result;
}
///
/// Check two Instance of Typed Object Values are Same or not
///
///
///
///
///
///
///
/// ///
///
///
public static bool IsSameContent(
this T source,
D dest,
ICollection propertyWhiteList = null,
ICollection propertyBlackList = null,
ICollection>> propertyValueCheckers = null,
bool throwExceptionOnFails = false
)
where T : class
where D : class
{
//
var hasWhiteList = propertyWhiteList.HasChild();
var hasBlackList = propertyBlackList.HasChild();
var hasCheckerProvider = propertyValueCheckers.HasChild>>();
//
var fullPropertyList = dest.GetType().GetProperties().Select(prop => prop.Name);
var mustCheckProps = (hasWhiteList ? propertyWhiteList : fullPropertyList);
if (hasBlackList)
{
mustCheckProps = mustCheckProps.Where(propName => !propertyBlackList.Contains(propName));
}
//
var result = true;
mustCheckProps.ToList().ForEach(propName =>
{
//
try
{
//
var sourceProp = source.GetType().GetProperty(propName);
var destProp = dest.GetType().GetProperty(propName);
//
// Check Types ...
var isSameType = true;
//
// Check
var isSameValue = false;
var mustDoCustomCheck = hasCheckerProvider && propertyValueCheckers.Any(p => p.Key == propName);
if (mustDoCustomCheck)
{
//
// Check Values ...
var valueChecker = propertyValueCheckers.FirstOrDefault(p => p.Key == propName).Value;
isSameValue = valueChecker.Invoke(source, dest);
}
else
{
// //
// isSameType = (sourceProp.PropertyType == destProp.PropertyType &&
// sourceProp.ReflectedType == destProp.ReflectedType);
//
// Check Values ...
isSameValue = Equals(sourceProp.GetValue(source), destProp.GetValue(dest));
}
//
if (!isSameType || !isSameValue)
{
result = false;
}
}
catch (Exception ex)
{
//
if (throwExceptionOnFails)
{
throw ex;
}
}
});
//
return result;
}
///
/// Check specific type is Collection Type or not
///
///
///
public static bool IsCollectionType(this Type source)
{
//
if (source.IsNull() || !source.IsGenericType)
{
return false;
}
//
var genericTypeDefinition = source.GetGenericTypeDefinition();
var result = genericTypeDefinition == typeof(List<>) ||
genericTypeDefinition == typeof(HashSet<>) ||
genericTypeDefinition == typeof(Collection<>) ||
genericTypeDefinition == typeof(ICollection<>) ||
genericTypeDefinition == typeof(IEnumerable<>);
//
return result;
}
///
/// Retrieve a Property Value in Generic
///
///
///
///
public static string GetPropValues(this T item)
where T : class
{
//
var props = item.GetType().GetProperties();
var vals = props.Select(p => p.GetValue(item));
//
return vals.ToJSON();
}
///
/// Check a Property Value Contains specific value
///
///
///
///
///
public static bool PropValuesContains(this T item, string value)
where T : class
{
//
return item.GetPropValues()
.ToNormalString()
.Contains(value
.ToNormalString());
}
///
/// Generate Default Column Map
///
///
///
///
public static IDictionary>> GetDefaultColumnsMap(this T item)
where T : class
{
//
if (item.IsNull())
{
return null;
}
//
var result = new Dictionary>>();
var props = item.GetType().GetProperties();
//
foreach (var prop in props)
{
result.Add(prop.Name, t => t.GetType().GetProperty(prop.Name).GetValue(t, null));
}
//
return result;
}
///
/// Generate Default Column Map
///
///
///
///
public static IDictionary GetPropValuesDictionary(this T item)
where T : class
{
//
if (item.IsNull())
{
return null;
}
//
var result = new Dictionary();
var props = item.GetType().GetProperties();
//
foreach (var prop in props)
{
result.Add(prop.Name, prop.GetValue(item).ToJSON());
}
//
return result;
}
}
}