属性链末尾 属性 的 PropertyInfo
PropertyInfo for property at the end of a chain of properties
我有这样的东西:
class OriginalClass
{
public Type2 object2 { get; set; }
}
class Type2
{
public Type3 object3 { get; set; }
}
class Type3
{
public Type4 object4 { get; set; }
}
var obj = new OriginalClass();
var object4 = obj.object2.object3.object4;
我还有一个字符串值:
"object2.object3.object4"
这是从类型 T
到 object4
通过 object2
和 object3
(returns 对象的两个属性)的路径。 object4
是 object3
上的 属性。
如何为最后一个 属性 "object4"
动态创建 PropertyInfo
对象?
您可以实现如下扩展方法:
public static class TypeExtensions
{
/// <summary>Looks for a property using an object path where each
/// property to match is accessed using dot syntax</summary>
public static PropertyInfo GetPropertyByPath(this Type someType, string objectPath, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public)
{
string[] objectPathParts = objectPath.Split('.');
// #1 property in the object path should be obtained from T
PropertyInfo currentProperty = someType.GetProperty(objectPathParts[0], bindingFlags);
for (int propertyIndex = 1; propertyIndex < objectPathParts.Length; propertyIndex++)
{
// While all other association properties should be obtained
// accessing PropertyInfo.PropertyType
currentProperty = currentProperty.PropertyType.GetProperty(objectPathParts[propertyIndex], bindingFlags);
if (currentProperty == null)
throw new ArgumentException("Some property in the object path doesn't exist", "objectPath");
}
return currentProperty;
}
}
以后使用如下:
PropertyInfo object4Info = typeof(OriginalClass).GetPropertyByPath("object2.object3.object4");
方法 2:使用表达式树。更好更简单!
您也可以使用较少的反射来解决问题:
public static class ReflectionHelper
{
public static PropertyInfo GetPropertyByPath<T>(Expression<Func<T, object>> pathExpr)
{
// It must be a member access expression like "x.y.z"
MemberExpression propertyAccessExpr = pathExpr.Body as MemberExpression;
// if it's not a member access expression, return null
if(propertyAccessExpr == null)
return null;
return propertyAccessExpr.Member as PropertyInfo;
}
}
然后在路径中获取最后的 属性 信息如下:
PropertyInfo object4Info = ReflectionHelper
.GetPropertyByPath<OriginalClass>(c => c.object2.object3.object4);
使用下面的代码,您可以执行如下操作:
PropertyInfo pi = GetPropertyInfoFromPath(obj.GetType(), "object2.object3.object4");
我仍然需要抽出时间将其作为金块发布,但这是我的反思库的摘录。
public static PropertyInfo GetPropertyInfoFromPath<T>(string path)
{
var type = typeof(T);
return GetPropertyInfoFromPath(type, path);
}
public static PropertyInfo GetPropertyInfoFromPath(Type type, string path)
{
var parts = path.Split('.');
var count = parts.Count();
if (count == 0)
throw new InvalidOperationException("Not a valid path");
if (count == 1)
return GetPropertyInformation(type, parts.First());
else
{
var t = GetPropertyInformation(type, parts[0]).PropertyType;
return GetPropertyInfoFromPath(t, string.Join(".", parts.Skip(1)));
}
}
如果您确实想使用表达式(如果可能更好,因为它是重构安全的)
public static Type GetPropertyType<T>(Expression<Func<T, object>> expression)
{
var info = GetPropertyInformation(expression) as PropertyInfo;
return info.PropertyType;
}
public static MemberInfo GetPropertyInformation<T>(Expression<Func<T, object>> propertyExpression)
{
return PropertyInformation(propertyExpression.Body);
}
public static PropertyInfo PropertyInformation(Expression propertyExpression)
{
MemberExpression memberExpr = propertyExpression as MemberExpression;
if (memberExpr == null)
{
UnaryExpression unaryExpr = propertyExpression as UnaryExpression;
if (unaryExpr != null && unaryExpr.NodeType == ExpressionType.Convert)
{
memberExpr = unaryExpr.Operand as MemberExpression;
}
}
if (memberExpr != null)
{
var propertyMember = memberExpr.Member as PropertyInfo;
if (propertyMember != null)
return propertyMember;
}
return null;
}
测试。
[Fact]
public void GetPropertyInfo_FromInstanceNestedPropertyUsingPathString_ReturnsPropertyInfo()
{
var deepType = Helper.GetPropertyInfoFromPath<TestModel>("Nested.Deep");
var deepDeclaringType = Helper.GetPropertyInfoFromPath<TestModel>("Nested");
Assert.Equal(typeof(string), deepType.PropertyType);
Assert.Equal(typeof(NestedModel), deepDeclaringType.PropertyType);
}
类.
public class TestModel : Base
{
public int Id { get; set; }
[PickMe]
public string MyString { get; set; }
public NestedModel Nested { get; set; }
public DateTime ClosedAt { get; set; }
}
public class NestedModel
{
public string Deep { get; set; }
}
我有这样的东西:
class OriginalClass
{
public Type2 object2 { get; set; }
}
class Type2
{
public Type3 object3 { get; set; }
}
class Type3
{
public Type4 object4 { get; set; }
}
var obj = new OriginalClass();
var object4 = obj.object2.object3.object4;
我还有一个字符串值:
"object2.object3.object4"
这是从类型 T
到 object4
通过 object2
和 object3
(returns 对象的两个属性)的路径。 object4
是 object3
上的 属性。
如何为最后一个 属性 "object4"
动态创建 PropertyInfo
对象?
您可以实现如下扩展方法:
public static class TypeExtensions
{
/// <summary>Looks for a property using an object path where each
/// property to match is accessed using dot syntax</summary>
public static PropertyInfo GetPropertyByPath(this Type someType, string objectPath, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public)
{
string[] objectPathParts = objectPath.Split('.');
// #1 property in the object path should be obtained from T
PropertyInfo currentProperty = someType.GetProperty(objectPathParts[0], bindingFlags);
for (int propertyIndex = 1; propertyIndex < objectPathParts.Length; propertyIndex++)
{
// While all other association properties should be obtained
// accessing PropertyInfo.PropertyType
currentProperty = currentProperty.PropertyType.GetProperty(objectPathParts[propertyIndex], bindingFlags);
if (currentProperty == null)
throw new ArgumentException("Some property in the object path doesn't exist", "objectPath");
}
return currentProperty;
}
}
以后使用如下:
PropertyInfo object4Info = typeof(OriginalClass).GetPropertyByPath("object2.object3.object4");
方法 2:使用表达式树。更好更简单!
您也可以使用较少的反射来解决问题:
public static class ReflectionHelper
{
public static PropertyInfo GetPropertyByPath<T>(Expression<Func<T, object>> pathExpr)
{
// It must be a member access expression like "x.y.z"
MemberExpression propertyAccessExpr = pathExpr.Body as MemberExpression;
// if it's not a member access expression, return null
if(propertyAccessExpr == null)
return null;
return propertyAccessExpr.Member as PropertyInfo;
}
}
然后在路径中获取最后的 属性 信息如下:
PropertyInfo object4Info = ReflectionHelper
.GetPropertyByPath<OriginalClass>(c => c.object2.object3.object4);
使用下面的代码,您可以执行如下操作:
PropertyInfo pi = GetPropertyInfoFromPath(obj.GetType(), "object2.object3.object4");
我仍然需要抽出时间将其作为金块发布,但这是我的反思库的摘录。
public static PropertyInfo GetPropertyInfoFromPath<T>(string path)
{
var type = typeof(T);
return GetPropertyInfoFromPath(type, path);
}
public static PropertyInfo GetPropertyInfoFromPath(Type type, string path)
{
var parts = path.Split('.');
var count = parts.Count();
if (count == 0)
throw new InvalidOperationException("Not a valid path");
if (count == 1)
return GetPropertyInformation(type, parts.First());
else
{
var t = GetPropertyInformation(type, parts[0]).PropertyType;
return GetPropertyInfoFromPath(t, string.Join(".", parts.Skip(1)));
}
}
如果您确实想使用表达式(如果可能更好,因为它是重构安全的)
public static Type GetPropertyType<T>(Expression<Func<T, object>> expression)
{
var info = GetPropertyInformation(expression) as PropertyInfo;
return info.PropertyType;
}
public static MemberInfo GetPropertyInformation<T>(Expression<Func<T, object>> propertyExpression)
{
return PropertyInformation(propertyExpression.Body);
}
public static PropertyInfo PropertyInformation(Expression propertyExpression)
{
MemberExpression memberExpr = propertyExpression as MemberExpression;
if (memberExpr == null)
{
UnaryExpression unaryExpr = propertyExpression as UnaryExpression;
if (unaryExpr != null && unaryExpr.NodeType == ExpressionType.Convert)
{
memberExpr = unaryExpr.Operand as MemberExpression;
}
}
if (memberExpr != null)
{
var propertyMember = memberExpr.Member as PropertyInfo;
if (propertyMember != null)
return propertyMember;
}
return null;
}
测试。
[Fact]
public void GetPropertyInfo_FromInstanceNestedPropertyUsingPathString_ReturnsPropertyInfo()
{
var deepType = Helper.GetPropertyInfoFromPath<TestModel>("Nested.Deep");
var deepDeclaringType = Helper.GetPropertyInfoFromPath<TestModel>("Nested");
Assert.Equal(typeof(string), deepType.PropertyType);
Assert.Equal(typeof(NestedModel), deepDeclaringType.PropertyType);
}
类.
public class TestModel : Base
{
public int Id { get; set; }
[PickMe]
public string MyString { get; set; }
public NestedModel Nested { get; set; }
public DateTime ClosedAt { get; set; }
}
public class NestedModel
{
public string Deep { get; set; }
}