vendredi 5 août 2022

How to dynamically query IQueryable array by each property using reflection?

I have search method with gets as parameter some DTO and make where filtering dynamically by DTO properties. The problem I get when using reflection is that I should explicitly cast to a property type that I am using. Is there a way to make it dynamic too so that the method that that make filtering can work without knowing type of a property. I am using Dynamic Ling Library.

CODE:

 public async Task<ServiceResponceWithData<List<SearchResponseDTO>>> SearchAsync(SearchDTO model)
    {
        var users = from user in _userManeger.Users
                    join ur in _context.UserRoles
                           on user.Id equals ur.UserId
                    select new SearchResponseDTO
                    {
                        UserName = user.UserName,
                        Email = user.Email,
                        PhoneNumber = user.PhoneNumber,
                        FirstName = user.FirstName,
                        LastName = user.LastName,
                        Roles = _roleManager.Roles
                                .Where(c => c.Id == ur.RoleId)
                                .Select(c => c.Name)
                                .ToList()
                    };

        var startResult = users;

        var props = typeof(SearchDTO).GetProperties();
        foreach (var prop in props)
        {
            if(prop.Name != "Role")
            {
                users = FilterWithWhereByStringTypeProperty(users, prop, model);
            }
            else
            {
                if (model.Role != null)
                {
                    var results = users.Where(c => c.Roles.Any(r => r == model.Role));
                    users = results.Any() ? results : users;
                }
            }
        }

        var endResultList =  startResult == users ? new List<SearchResponseDTO>() :await  users.ToListAsync();

        return new ServiceResponceWithData<List<SearchResponseDTO>>() { Data = endResultList, Success = true };
    }

    private IQueryable<SearchResponseDTO> FilterWithWhereByStringTypeProperty(IQueryable<SearchResponseDTO> collection,
                                                PropertyInfo property,SearchDTO model )
    {
        var propertyName = property.Name;
        var modelPropVal = property.GetValue(model);

        if (modelPropVal == null) return collection;

        string val = (string)modelPropVal;
        string condition = String.Format("{0} == \"{1}\"", propertyName, val);
        var fillteredColl = collection.Where(condition);
        return fillteredColl.Any() ? fillteredColl : collection;
    }
}




Aucun commentaire:

Enregistrer un commentaire