我想要做的是获取任何类类型,并为对象图中的所有属性创建一个"获取"访问器列表.
集合的确切格式,顺序等并不重要,我只是不知道如何开始识别和创建所有属性的访问器.它可能采取以下形式:
public static List<Func<T,object>> CreateAccessors<T>()
{
Type t = typeof(T);
// Identify all properties and properties of properties (etc.) of T
// Return list of lambda functions to access each one given an instance of T
}
public void MyTest()
{
MyClass object1;
var accessors = CreateAccessors<MyClass>();
var myVal1 = accessors[0](object1);
var myVal2 = accessors[1](object1);
// myVal1 might now contain the value of object1.Property1
// myVal2 might now contain the value of object1.Property4.ThirdValue.Alpha
}
Run Code Online (Sandbox Code Playgroud)
您可以使用反射来提取属性和表达式树,以帮助构建以属性getter为目标的委托:
// Start with all public instance properties of type
var accessors = from property in type.GetProperties
(BindingFlags.Instance | BindingFlags.Public)
// Property must be readable
where property.CanRead
//Assemble expression tree of the form:
// foo => (object) foo.Property
// foo
let parameter = Expression.Parameter(type, "foo")
// foo.Property
let propertyEx = Expression.Property(parameter, property)
// (object)foo.Property - We need this conversion
// because the property may be a value-type.
let body = Expression.Convert(propertyEx, typeof(object))
// foo => (object) foo.Property
let expr = Expression.Lambda<Func<T,object>>(body, parameter)
// Compile tree to Func<T,object> delegate
select expr.Compile();
return accessors.ToList();
Run Code Online (Sandbox Code Playgroud)
请注意,尽管Delegate.CreateDelegate看起来是一个明显的选择,但是在装箱值类型属性时会遇到一些问题.表达树优雅地躲避这个问题.
请注意,您还需要一些工作才能获得"嵌套"属性,但希望我已经给予ypu足以让您入门(提示:recurse).最后一个指针:注意对象图中的循环!