user1949790
user1949790

Reputation: 21

CategoryAttribute and PropertyInfo

I have a class that includes several hundred Properties. Each of the properties was declared with a [CategoryAttribute("My Category Name")] attribute clause so that it will display nicely in a PropertyGrid. I would like to make use of this same CategoryAttribute attribute to set the values of all the properties in the class that were labeled with specific categoryAttribute catagories. The code below compiles and runs but it doesn't accomplish the task because att_coll doesn't contain the CategoryAttribute attribute that I expected that it would. Does anyone know how to do this? Thanks so much.

    class my_class
    {
        [CategoryAttribute("Category One")]
        public int property_1
        {
             get { return _property_1; }
             set { _property_1 = value; }
        }

        [CategoryAttribute("Category One")]
        public int property_2
        {
             get { return _property_2; }
             set { _property_2 = value; }
        }
    }

    void ClearCatagory(string category_name)
    {
        CategoryAttribute target_attribute = new CategoryAttribute(category_name);

        Type my_class_type = my_class.GetType();
        PropertyInfo[] prop_info_array = my_class_type.GetProperties();

        foreach (PropertyInfo prop_info in prop_info_array)
        {
            AttributeCollection att_coll = TypeDescriptor.GetAttributes(prop_info);

            CategoryAttribute ca = (CategoryAttribute) att_col[typeof(CategoryAttribute)];

            if (ca.Equals(target_attribute))
            {
                prop_info.SetValue(my_class, 0, null);
            } 
        }
    }

Upvotes: 2

Views: 5479

Answers (3)

Pravin
Pravin

Reputation: 1

public class cls
{
        [Category("Default")]
        [DisplayName("Street")]
        public string Street { get; set; }
}

foreach (PropertyInfo propinf in cls.GetProperties())
{
  var category = prop.CustomAttributes.Where(x => x.AttributeType ==typeof(CategoryAttribute)).First();
sCategory = category.ConstructorArguments[0].Value.ToString();
}

This is how we could get value of CustomAttribute

Upvotes: 0

user1949790
user1949790

Reputation: 21

Thanks so much to shf301 for solving this. Here is a working version of the code:

    class my_class
    {
        [CategoryAttribute("Category One")]
        public int property_1
        {
                get { return _property_1; }
                set { _property_1 = value; }
        }
    }

    void ClearCatagory(string category_name)
    {
        Type my_class_type = my_class.GetType();
        PropertyInfo[] prop_info_array = my_class_type.GetProperties();

        foreach (PropertyInfo prop_info in prop_info_array)
        {
            CategoryAttribute[] attributes = (CategoryAttribute[]) prop_info.GetCustomAttributes(typeof(CategoryAttribute), false);
            foreach(CategoryAttribute ca in attributes)
            {
                if (ca.Category == category_name)
                {
                    prop_info.SetValue(my_class, 0, null);
                }
            }
        }
    }

Upvotes: 0

shf301
shf301

Reputation: 31404

Use the MemberInfo.GetCustomAttributes instance method instead of TypeDescriptor.GetAttriburtes.

The call would be object[] attributes = prop_info.GetCustomAttributes(typeof(CategoryAttriute), false).

Or you could use TypeDescriptor.GetProperties instead of Type.GetProperties You shouldn't switch between using reflection and TypeDescriptor.


Also, the documentation for Category.Equals isn't exactly clear, but likely it implements reference equality (which is the default for C# unless a class specifically overrides it). Which means that Equals will only return true if the instances being compared are exactly the same regardless of the value of Category. If that is the case, then ca.Equals(target_attribute) will always be false because the references are different objects.

Try instead comparing the string value stored in the Category value. Strings implement value equality so that String.Equals compares the values stored in the stings.

So replace

if (ca.Equals(target_attribute))

with

if (ca.Cateogry.Equals(category_name))

Upvotes: 2

Related Questions