using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
namespace xCommons.Extensions {
public static partial class ModelExtensions {
///
/// 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 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;
}
}
}