简体   繁体   中英

Get nested generic type object's property and attribute values through Reflection at run time

I created a custom attribute class

    [AttributeUsage(AttributeTargets.Property)]
    public class MyCustomAttribute : Attribute
    {
       public string Name{ get; set; }
    }

I have a complex nested object below:


    public class Parent
    {
       [MyCustom(Name = "Parent property 1")]
       public string ParentProperty1 { get; set; }

       [MyCustom(Name = "Parent property 2")]
       public string ParentProperty2 { get; set; }

       public Child ChildObject { get; set; }
    }

    public class Child
    {
        [MyCustom(Name = "Child property 1")]
        public string ChildPropery1 { get; set; }

        [MyCustom(Name = "Child property 2")]
        public string ChildProperty2 { get; set; }
    }

I want to get the list of property names, attribute name value for each property if this object is passed in as a generic object at run time, how can I do this if the input object at run-time is "Parent"?

I know how to do this for a flat structure generic object using the code below, but I'm unsure how to retrieve all nested object property and attribute, do I need to use some sort of recursive function?

public void GetObjectInfo<T>(T object)
{
   //Get the object list of properties.
   var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

   foreach (var property in properties)
   {
      //Get the attribute object of each property.
      var attribute = property.GetCustomAttribute<MyCustomAttribute>();
   }
}

Note, the object I used is a very simplistic version of what is in real life, I could have multiple level of nested child or nested list/array ect..

You can create a function that recursively enumerates properties with your custom attribute.

public static IEnumerable<PropertyInfo> EnumeratePropertiesWithMyCustomAttribute(Type type)
{
    if (type == null)
    {
        throw new ArgumentNullException();
    }
    foreach (PropertyInfo property in type.GetProperties())
    {
        if (property.HasCustomAttribute<MyCustomAttribute>())
        {
            yield return property;
        }
        if (property.PropertyType.IsReferenceType && property.PropertyType != typeof(string)) // only search for child properties if doing so makes sense
        {
            foreach (PropertyInfo childProperty in EnumeratePropertiesWithMyCustomAttributes(property.PropertyType))
            {
                yield return childProperty;
            }
        }
    }
}

Note: this function accepts a type. To call it on an object:

public static IEnumerable<PropertyInfo> EnumeratePropertiesWithMyCustomAttributes(object obj)
{
    if (obj == null)
    {
        throw new ArgumentNullException();
    }
    return EnumeratePropertiesWithMyCustomAttributes(obj.GetType());
}

To get the full list:

Parent parent = new Parent();
PropertyInfo[] propertiesWithMyCustomAttribute = EnumeratePropertiesWithMyCustomAttributes(parent).ToArray();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM