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 ) where T : class { // var result = source .GetType() .GetProperties() .Any(prop => prop.Name == property); ; // return result; } /// /// Check a Class is Contains a Filed or not ... /// /// /// /// /// public static bool HasField( this T source, string filed ) where T : class { // var result = source .GetType() .GetFields() .Any(fld => fld.Name == filed); // return result; } /// /// Check a Class is Contains a Method or not ... /// /// /// /// /// public static bool HasMethod( this T source, string method ) where T : class { // var result = source .GetType() .GetMethods() .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[] GetFiledsNames( 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 ) where T : class { // TProp result = default(TProp); // // Check if T Has Property ... if (source.HasProperty(property)) { // // Access Property ... var prop = source .GetType() .GetProperty(property); // // 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 filed ) where T : class { // TField result = default; // if (source.HasField(filed)) { // var fld = source .GetType() .GetField(filed); // 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 ) where T : class { // // Check T Has Property ... var result = source.HasProperty(property); if (!result) { return result; } // // Access Property ... var prop = source .GetType() .GetProperty(property); // // 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 filed, TField value ) where T : class { // // Check T Has Field ... var result = source.HasField(filed); if (!result) { return result; } // // Access Field ... var fld = source .GetType() .GetField(filed); // // 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; } } }