Reputation: 21
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
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
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
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