Recursively find object property via reflection?

Let's say I have class,

class A
{
  B PropA{get; set;}
}

class B
{
  string PropB{get; set;}
  C PropC{get; set;}
}

class C
{
  string PropD{get; set;}
}

Now I wanna get "PropA.PropB"? Similarly, I wanna get "PropA.PropC.PropD" and so on? I need to create a method that will take "PropA.PropB" as parameter and return the PropetyInfo?

Upvotes: 2

Views: 1437

Answers (4)

Leo Nix
Leo Nix

Reputation: 2105

I've made your properties public to make the sample below work:

static void Main(string[] args)
{

    var propertyInfo = GetPropertyInfo(typeof(A), "PropA.PropC");
    Console.WriteLine(propertyInfo.Name);
    Console.ReadLine();
}

static PropertyInfo GetPropertyInfo(Type type, string propertyChain)
{
    if (!propertyChain.Contains("."))
    {
        var lastProperties = type.GetProperties().Where(m => m.Name.Equals(propertyChain));
        return lastProperties.Any() ? lastProperties.First() : null;
    }

    var startingName = propertyChain.Split('.')[0];
    var found = type.GetProperties().Where(m => m.Name.Equals(startingName));
    return found.Any() ? GetPropertyInfo(found.First().PropertyType, propertyChain.Replace(startingName + ".", "")) : null;
}

Upvotes: 1

Fabjan
Fabjan

Reputation: 13676

Assuming that we do not know names of properties for PropA, PropC but only know their types and we also know the name for property string PropD in target class C :

class A
{
    public B PropA { get; set; }
}

class B
{
    public string PropB { get; set; }
    public C PropC { get; set; }
}

class C
{
    public string PropD { get; set; }
}

class Program
{
    static object GetPValue(Type propType, object obj)
    {
        return obj.GetType().GetProperties()
            .First(p => p.PropertyType == propType).GetValue(obj);
    }

    static object GetPValue(string name, object obj)
    {
        return obj.GetType().GetProperty(name).GetValue(obj);
    }

    static void Main(string[] args)
    {
        A a = new A();
        B b = new B();
        C c = new C();
        a.PropA = b;
        b.PropB = "B";
        b.PropC = c;
        c.PropD = "C";

        object obj = new object();

        obj = GetPValue(typeof(C), GetPValue(typeof(B), a));

        Console.WriteLine(GetPValue("PropD", obj));
    }
}

Output : C

Upvotes: 1

Sagi
Sagi

Reputation: 9284

static class Program
{
    static readonly BindingFlags flags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

    static void Main() {
        var a = new A { PropA = new B() { PropB = "Value" } };
        var prop = GetPropertyRecursive("PropA.PropB", a);
    }

    static object GetPropertyRecursive(string property, object obj) {
        var splitted = property.Split('.');
        var value = obj.GetType().GetProperty(splitted[0], flags).GetValue(obj);

        if (value == null) {
            return null;
        }

        if (splitted.Length == 1) {
            return value;
        }

        return GetPropertyRecursive(string.Join(".", splitted.Skip(1)), value);
    }
}

Upvotes: 1

Guilherme Fidelis
Guilherme Fidelis

Reputation: 1020

I do not quite understand your question...

If you want to get the names of class properties, you can do:

using System.Linq;
using System.Reflection;

List<Type> properties = GetTypesInNamespace(Assembly.GetExecutingAssembly(), "YourClassNameSpace");

 var propertiesNames = properties.Select(p => p.Name);

private List<Type> GetTypesInNamespace(Assembly assembly, string nameSpace)
{
    return assembly.GetTypes().Where(t => String.Equals(t.Namespace, nameSpace, StringComparison.Ordinal)).ToList();
}

Upvotes: 0

Related Questions