vendredi 14 juillet 2023

Update entity related objects using reflection

hy everyone. i am trying to update the entity related objects using reflection. my current appproach is to look for parent properties of entity. if incoming property name is found then get its value. if not then get all the relatedObjects. and start looking for propertyName. if property name is found then return the propertyInfo with the related Object. my current object looks like this

`class UserArea{
        public int Id { get; set; }

        public Department Department { get; set; }
        public int DepartmentId  { get; set; }
        
        public Area Area  { get; set; }
        public int AreaId  { get; set; }
        public User User { get; set; }
        public string UserId { get; set; }
}`

i receive the parameters to update with thier values in dictionary<string,object> the problem is i dont receive complete object with all related properties filled. i.e if i to update User name property then i would receive {fullName: "userName" } in dictionary. now its upto me to look up for property in all the related objects. but that is not the problem. the problem when i found the property i am unable to set its value in the parent entity object because its null there and c# does not set properties that way.

this is what i have tried. it works fine and finds the property in related objects. but does not sets the propery back in parent entity object

        private async Task<TEntity?> EditObject<TEntity>(int key, Dictionary<string, string> properties)
        {
            if (key <= 0 || properties == null)
            {
                throw new ArgumentException("Invalid input parameters");
            }

            var setMethod = typeof(UsafeDbContext).GetMethod(nameof(UsafeDbContext.Set), Type.EmptyTypes);
            var dbSet = setMethod.MakeGenericMethod(typeof(TEntity)).Invoke(_context, null);

            var filteredResult = ((IQueryable<TEntity>)dbSet).AsEnumerable().Where(entity => entity.GetType().GetProperty("Id").GetValue(entity).ToString() == key.ToString());

            var entityObject = filteredResult.FirstOrDefault();


            var entityKeys = typeof(TEntity).GetProperties();

            foreach (var propKey in properties.Keys)
            {
                var propertyName = propKey.ToLower(); // Modify to handle case sensitivity if desired

                var (propertyInfo, relatedObject) = FindProperty(entityKeys, propertyName, entityObject).Value;
                if (propertyInfo != null)
                {
                    try
                    {
                        var propertyType = propertyInfo.PropertyType;
                        var propertyValue = Convert.ChangeType(properties[propKey], propertyType);
                        if (propertyType.IsEnum)
                        {
                            propertyValue = Enum.Parse(propertyType, properties[propKey]);
                        }
                        propertyInfo.SetValue(entityObject, propertyValue);
                    }
                    catch (Exception ex)
                    {
                        // Properly handle or log the exception
                        Console.WriteLine($"{ex.Message}\r\n {ex.StackTrace}");
                    }
                }

                else if (relatedObject != null)
                {
                    var relatedPropertyInfo = relatedObject.GetType().GetProperty(propertyName);
                    if (relatedPropertyInfo != null)
                    {
                        try
                        {
                            var propertyType = relatedPropertyInfo.PropertyType;
                            var propertyValue = Convert.ChangeType(properties[propKey], propertyType);
                            if (propertyType.IsEnum)
                            {
                                propertyValue = Enum.Parse(propertyType, properties[propKey]);
                            }
                            relatedPropertyInfo.SetValue(relatedObject, propertyValue);
                        }
                        catch (Exception ex)
                        {
                            // Properly handle or log the exception
                            Console.WriteLine($"{ex.Message}\r\n {ex.StackTrace}");
                        }
                    }
                }
            }

            return entityObject;
        }


        private (PropertyInfo PropertyInfo, object RelatedObject)? FindProperty(PropertyInfo[] entityKeys, string propertyName, object entityObject)
        {
            var topProps = entityKeys
                .FirstOrDefault(x =>
                    x.Name.ToLower() == propertyName && x.GetCustomAttribute(typeof(IgnorePropertyAttribute)) is null);
            if (topProps is not null)
                return (topProps, null);

            var relatedObjects = entityKeys
                .Where(p => p.PropertyType.IsClass && p.PropertyType.Namespace == "usafe.Models")
                .ToList();

            foreach (var relatedObject in relatedObjects)
            {
                var relatedEntity = relatedObject.PropertyType.GetProperties().FirstOrDefault(x => x.Name.ToLower() == propertyName);
                if (relatedEntity != null)
                {
                    if (relatedEntity.GetCustomAttribute(typeof(IgnorePropertyAttribute)) is null)
                    {
                        var relatedPropertyValue = relatedObject.GetValue(entityObject);
                        return (relatedEntity, relatedPropertyValue);
                    }
                }
            }
            return null;
        }




Aucun commentaire:

Enregistrer un commentaire