Question

I have two classes:

public class LookUpData 
{
  [Searchable]
  public string ManufactureName {get;set;)
}

public class Car
{
   public int ID {get;set;}
   [Searchable]  
   public string  Model {get;set;}
   public int ManufactureId {get;set;} 
   public LookUpData LookUpData{ get;set;} 

}

With [Searchable] attiribute I'm trying to get properties on which after I can make search in DB.

Currently I have static medthod:

public static List<PropertyInfo> GetSearchPropertiesWithOrderBy(Type type)
{
  if (type == null) throw new ArgumentNullException("type");

  return type.GetProperties()
             .Select(x => new
                            {
                              Property = x,
                              Attribute =
                            (SearchableAttribute) Attribute.GetCustomAttribute(x, typeof (SearchableAttribute), true)
                            })
             .OrderBy(x => x.Attribute != null ? x.Attribute.OrderBy : 200)
             .Select(x => x.Property)
             .ToList();
}

I can get a List of PropertyInfo's

 - Model 
 - LookUpData

How Can I Get List of PropertyInfo's to have "real name" properties:

 - Model   
 - ManufacterName

Thanks in advance.

Was it helpful?

Solution

This will work for all your classes if the hierarchy is one, two ,three, four levels etc too. Only thing missing is OrderBy. I believe that piece can be done by you once the listing is got.

    public static List<PropertyInfo> GetSearchProperties(Type type)
    {
        if (type == null) throw new ArgumentNullException("type");


        List<PropertyInfo> propL = new List<PropertyInfo>();
        foreach (var item in type.GetProperties())
        {
            object[] obj = item.GetCustomAttributes(typeof(Searchable), true);
            if (obj.Count() > 0)
            {
                propL.Add(item);
            }
            else
            {                    
                propL.AddRange(GetSearchPropertiesWithOrderBy(item.PropertyType));
            }
        }
        return propL;        
    }
    [System.AttributeUsage(System.AttributeTargets.Property)]
    public class Searchable : System.Attribute
    {

    }
    public class LookUpData
    {
        [Searchable]
        public string ManufactureName { get; set; }
    }

    public class Car
    {
        public int ID { get; set; }
        [Searchable]
        public string Model { get; set; }
        public int ManufactureId { get; set; }
        public LookUpData LookUpData { get; set; }

    }

With hierarchy it means if your LookUpData property was not declared directly in Car class For example, then too this code will work perfectly fine.

    public class MyDataModels
    {
        LookUpData MysetOfData { get; set; }
        int MyVal { get; set; }
    }

    public  class MyCar
    {
        public int ID { get; set; }
        [Searchable]
        public string Model { get; set; }
        public int ManufactureId { get; set; }
        public MyDataModels MyModel { get; set; }

    }

OTHER TIPS

Based on your clarification comment, you want to give a nested instance the name of it's property. In case you don't want to name the property containing the instance with the name of its property, try the following.

Given the following SearchableAttribute:

public class SearchableAttribute : Attribute
{
    public int OrderBy { get; set; }

    public string SearchablePropertyName { get; set; }
}

You should extract the properties' attributes recursively (this is a depth-first approach, you can do it also breadth-first):

private static SearchableAttribute GetNestedSearchableAttribute(PropertyInfo propertyInfo)
{
    var attribute = (SearchableAttribute)Attribute.GetCustomAttribute(propertyInfo, typeof(SearchableAttribute), true);
    if (attribute == null)
    {
        return propertyInfo
            .PropertyType
            .GetProperties()
            .Select(GetNestedSearchableAttribute)
            .FirstOrDefault(attrib => attrib != null);
    }

    attribute.SearchablePropertyName = propertyInfo.Name;

    return attribute;
}

And you return not only the PropertyInfo, but an info together with the description, like this:

public static List<Tuple<PropertyInfo, string>> GetSearchPropertiesWithOrderBy(Type type)
{
    if (type == null)
        throw new ArgumentNullException("type");

    return type
        .GetProperties()
        .Select(
            x =>
            {
                var searchableAttribute = GetNestedSearchableAttribute(x);
                var description = new
                {
                    Property = x,
                    Attribute = searchableAttribute,
                    Name = searchableAttribute == null ? x.Name : searchableAttribute.SearchablePropertyName
                };

                return description;

            })
        .OrderBy(x => x.Attribute != null ? x.Attribute.OrderBy : 200)
        .Select(x => Tuple.Create(x.Property, x.Name))
        .ToList();
}

Hope that's what you need.

Try

.Select(x => new
             {
                 Property = x.Name,
                 ...

You can use an additional recursive method to collect inner properties, too.

like this,

    public static void GetAllSearchPropertiesWithOrderBy(Type type, ref List<PropertyInfo> result)
    {
        result = result ?? new List<PropertyInfo>();
        foreach (var propertyInfo in GetSearchPropertiesWithOrderBy(type))
        {
            result.Add(propertyInfo);
            GetAllSearchPropertiesWithOrderBy(propertyInfo.PropertyType, ref result);
        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top