using System.Text.RegularExpressions;
using System.Collections.Generic;
public static void Main(string[] s)
var a1 = new A(new B(new C[] { new C(1), new C(2), new C(3) }));
Console.WriteLine(GetFieldValueByPath(a1, "b.cItems[2].target"));
var a2 = new A(new B(new C[] { } ));
Console.WriteLine(GetFieldValueByPath(a2, "b.cItems[2].target"));
var a3 = new A(new B(null));
Console.WriteLine(GetFieldValueByPath(a3, "b.cItems[2].target"));
public static object GetFieldValueByPath(object obj, string fieldPath)
BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
var splitted = fieldPath.Split('.');
var current = splitted[0];
var match = Regex.Match(current, @"\[([0-9]+)\]");
if (match.Groups.Count > 1)
current = fieldPath.Substring(0, match.Groups[0].Index);
index = int.Parse(match.Groups[1].Value);
value = obj.GetType().GetField(current, flags).GetValue(obj);
catch (NullReferenceException ex)
throw new Exception(string.Format("Wrong path provided: field '{0}' does not exist on '{1}'", current, obj));
if (splitted.Length == 1)
var asIList = (IList<object>)value;
if (asIList != null && asIList.Count >= index.Value)
value = asIList[index.Value];
return GetFieldValueByPath(value, string.Join(".", splitted.Skip(1)));
public A(B b) { this.b = b; }
public B(C[] cItems) { this.cItems = cItems; }
public C(int val) { this.target = val; }