通过字符串在对象图中查找属性

Kha*_*zor 9 c# reflection

我正在尝试使用任意 字符串访问嵌套类结构的各个部分.

鉴于以下(人为)课程:

public class Person
{
   public Address PersonsAddress { get; set; }
}

public class Adddress
{
   public PhoneNumber HousePhone { get; set; }
}

public class PhoneNumber
{
   public string Number { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我希望能够"PersonsAddress.HousePhone.Number"从对象的实例中获取Person对象.

目前我正在使用反射进行一些时髦的递归查找,但我希望有一些忍者有更好的想法.

作为参考,这是我开发的(蹩脚)方法:

private static object ObjectFromString(object basePoint, IEnumerable<string> pathToSearch)
{
   var numberOfPaths = pathToSearch.Count();

   if (numberOfPaths == 0)
     return null;

   var type = basePoint.GetType();
   var properties = type.GetProperties();

   var currentPath = pathToSearch.First();

   var propertyInfo = properties.FirstOrDefault(prop => prop.Name == currentPath);

   if (propertyInfo == null)
     return null;

   var property = propertyInfo.GetValue(basePoint, null);

   if (numberOfPaths == 1)
     return property;

   return ObjectFromString(property, pathToSearch.Skip(1));
}
Run Code Online (Sandbox Code Playgroud)

Sim*_*ier 14

您可以简单地使用标准的.NET DataBinder.Eval方法,如下所示:

object result = DataBinder.Eval(myPerson, "PersonsAddress.HousePhone.Number");
Run Code Online (Sandbox Code Playgroud)

  • @Maxim:还要注意,你必须放弃_.NET Framework 4 Client Profile_:http://msdn.microsoft.com/en-us/library/cc656912.aspx (3认同)

Bri*_*haw 5

过去我不得不做一些类似的事情。我采用了 lambda 方法,因为在编译它们之后我可以缓存它们。我已经删除了这段代码中的缓存。

我包括了一些单元测试来展示该方法的用法。我希望这是有帮助的。

private static object GetValueForPropertyOrField( object objectThatContainsPropertyName, IEnumerable<string> properties )
  {
     foreach ( var property in properties )
     {
        Type typeOfCurrentObject = objectThatContainsPropertyName.GetType();

        var parameterExpression = Expression.Parameter( typeOfCurrentObject, "obj" );
        Expression memberExpression = Expression.PropertyOrField( parameterExpression, property );

        var expression = Expression.Lambda( Expression.GetDelegateType( typeOfCurrentObject, memberExpression.Type ), memberExpression, parameterExpression ).Compile();

        objectThatContainsPropertyName = expression.DynamicInvoke( objectThatContainsPropertyName );
     }

     return objectThatContainsPropertyName;
  }

  [TestMethod]
  public void TestOneProperty()
  {
     var dateTime = new DateTime();

     var result = GetValueForPropertyOrField( dateTime, new[] { "Day" } );

     Assert.AreEqual( dateTime.Day, result );
  }

  [TestMethod]
  public void TestNestedProperties()
  {
     var dateTime = new DateTime();

     var result = GetValueForPropertyOrField( dateTime,  new[] { "Date", "Day" } );

     Assert.AreEqual( dateTime.Date.Day, result );
  }

  [TestMethod]
  public void TestDifferentNestedProperties()
  {
     var dateTime = new DateTime();

     var result = GetValueForPropertyOrField( dateTime, new[] { "Date", "DayOfWeek" } );

     Assert.AreEqual( dateTime.Date.DayOfWeek, result );
  }
Run Code Online (Sandbox Code Playgroud)