Search code examples
c#algorithmrecursionreflectionattributes

C# reflection get all property information inside the proerperties with custom attribute


I am writing a method for extracting all properties from an object (including properties of its own) with custom attribute . For example

  public class SomeModel
{

    [Custom]
    public string Name { get; set; }


    public string TestData { get; set; }

    [Custom]
    public string Surname { get; set; }

   public  InnerModel InnerModel { get; set; }
}

And Inner Model :

  public class InnerModel
{
    public string Id { get; set; } = "TestID";

    [Custom]
    public string Year { get; set; }

    public ThirdObject HidedObject { get; set; }
}

And the third one :

 public class ThirdObject
{
    [Custom]
    public string  HidedName { get; set; }
}

I need to find all properties with "Custom" attribute . Testing :

SomeModel model = new SomeModel()
        {
            Name = "farid",
            Surname = "Ismayilzada",
            TestData = "Test" ,
            InnerModel = new InnerModel() { Year ="2022" , HidedObject= New ThirdObject{ HidedName="Secret"}}
        };

I need to write the method

GetMyProperties(model) => List<PropInf>()
[PropertyName= Name,Value=Farid ,Route="Name" ]
[PropertyName= Surname,Value=Ismayilzada,Route="Surname" ]
[PropertyName= Year,Value=2022,Route="InnerModel.Year" ]
[PropertyName= HidedName,Value=Secret,Route="InnerModel.HidedObject.HidedName" ]

How to get this information ?


Solution

  • You can write a method like this :

    private static IEnumerable<PropInfo> GetPropertiesInfo(object obj, string route = "")
    {
        List<PropInfo> results = new List<PropInfo>();
    
        // You can filter wich property you want https://learn.microsoft.com/en-us/dotnet/api/system.reflection.propertyinfo?view=net-6.0
        var objectProperties = obj.GetType().GetProperties().Where(p => p.CanRead);
        foreach (var property in objectProperties) 
        {
            var value = property.GetValue(obj);
    
            if (property.PropertyType.IsClass && property.PropertyType != typeof(string))
            {
                results.AddRange(GetPropertiesInfo(value, route + property.Name + "."));
            }
            else
            {
                // Check if the property has the Custom Attribute
                var customAttributes = property.GetCustomAttributes<CustomAttribute>();
                if (!customAttributes.Any())
                    continue;
                // You can set a method in your Attribute : customAttributes.First().CheckIfNeedToStoreProperty(obj);
    
                results.Add(new PropInfo()
                {
                    PropertyName = property.Name,
                    Value = value,
                    Route = route + property.Name
                });
            }
    
        }
    
        return results;
    }
    
    public class PropInfo
    {
        public string PropertyName { get; set; }
        public object Value { get; set; }
        public string Route { get; set; }
    }
    
    public class CustomAttribute : Attribute
    {
        public bool CheckIfNeedToStoreProperty(object obj)
        {
            return true;
        }
    }