dimanche 1 décembre 2019

List of PropertyInfo is created inside LINQ query even though assigned to a variable

I am creating a list of properties having a certain (custom) attribute. The method that creates it GetQuickSearchFields gets called thousands of times if I just store that list in a variable. However, if I store the list in a private field, I get my desired behaviour (it gets called only when the public method is called). Why is that?

    public List<T> SearchEntitiesProperties<T>(IEnumerable<T> entities, string searchString) where T : class
    {
        var propertiesToSearchOn = GetQuickSearchFields<T>(); //this method gets called with every enumeration in the Where call
        List<T> result;
        result = entities.Where(e => SearchInProperties(e, propertiesToSearchOn, searchString)).ToList();
        return result;
    }

    private bool SearchInProperties(object entity, List<PropertyInfo> propertiesToSearchOn, string searchString)
    {
        foreach (var propertyInfo in propertiesToSearchOn)
        {
            if (propertyInfo.PropertyType == typeof(string) &&
                CheckSearchCriteriaForStringProperty((string)propertyInfo.GetValue(entity), searchString))
            {
                return true;
            }

            if (propertyInfo.PropertyType == typeof(int) &&
                CheckSearchCriteriaForIntProperty((int)propertyInfo.GetValue(entity), searchString))
            {
                return true;
            }

            if (CheckSearchCriteriaOther(propertyInfo.GetValue(entity), searchString))
            {
                return true;
            }
        }

        return false;
    }

    private List<PropertyInfo> GetQuickSearchFields<T>() where T : class
        => typeof(T)
            .GetProperties()
            .Where(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(QuickSearchFieldAttribute))).ToList();

    private bool CheckSearchCriteriaForIntProperty(int intPropertyValue, string searchString)
        => intPropertyValue > 0 && intPropertyValue.ToString().ToLower().Contains(searchString.ToLower());

    private bool CheckSearchCriteriaForStringProperty(string stringPropertyValue, string searchString)
        => !string.IsNullOrEmpty(stringPropertyValue) && stringPropertyValue.ToLower().Contains(searchString.ToLower());

    private bool CheckSearchCriteriaOther(object propertyValue, string searchString)
        => propertyValue != null && propertyValue.ToString().ToLower().Contains(searchString.ToLower());
}




Aucun commentaire:

Enregistrer un commentaire