using System; using System.Collections.Concurrent; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace StoreHub.Framework.Helpers; public static class ObjectHelper { private static readonly ConcurrentDictionary CachedObjectProperties = new(); public static void TrySetProperty( TObject obj, Expression> propertySelector, Func valueFactory, params Type[] ignoreAttributeTypes ) { TrySetProperty(obj, propertySelector, x => valueFactory(), ignoreAttributeTypes); } public static void TrySetProperty( TObject obj, Expression> propertySelector, Func valueFactory, params Type[] ignoreAttributeTypes ) { string cacheKey = $"{obj?.GetType().FullName}-" + $"{propertySelector}-" + $"{(ignoreAttributeTypes != null ? "-" + string.Join("-", ignoreAttributeTypes.Select(x => x.FullName)) : "")}"; PropertyInfo property = CachedObjectProperties.GetOrAdd( cacheKey, (name) => { if (propertySelector.Body.NodeType != ExpressionType.MemberAccess) { return null; } MemberExpression memberExpression = (MemberExpression)propertySelector.Body; PropertyInfo? propertyInfo = obj?.GetType() .GetProperties() .FirstOrDefault( x => x.Name == memberExpression.Member.Name && x.GetSetMethod(true) != null ); if (propertyInfo == null) { return null; } if ( ignoreAttributeTypes != null && ignoreAttributeTypes.Any( ignoreAttribute => propertyInfo.IsDefined(ignoreAttribute, true) ) ) { return null; } return propertyInfo; } ); property?.SetValue(obj, valueFactory(obj)); } }