c# - 使用反射类型 T 来创建表达式> 对于具有属性的属性
问题描述
我目前正在探索封装一些通常是迭代的逻辑的可行性。使用第 3 方库,它具有通用 Html Helper 方法,允许您将属性从 Generic T 类映射到表组件。通常你必须写一些东西来达到以下效果:
HtmlHelper.GenerateTable<ClassName>
.configure(tableDefinition =>{
// Adding each property you want to render here
tableDefinition.add(myClassRef => myClassRef.propertyA);
tableDefinition.add(myClassRef => myClassRef.propertyB);
})
我正在探索将属性添加到属性(例如标准 Display 属性)然后使用反射将该属性添加到容器的想法。该add
方法只接受 type 的参数Expression<Func<T, TValue>>
。以我目前对反射的理解,我知道我可以通过循环PropertyInfo
并检查我想要使用的属性来识别适用的属性GetCustomAttribute
。
我很难过的是是否可以使用反射来提供 add 方法期望的参数类型?
我将抛出到目前为止我已经开始使用的辅助方法逻辑。我的假设是,这将引导我走向 Expression 和 Lambda 类,但我无法充实任何有效的东西,因为我在技术上没有TValue
.
var t = typeof(T);
List<PropertyInfo> properties = t.GetProperties().ToList();
foreach(var prop in properties)
{
var attr = (DisplayAttribute[])prop.GetCustomAttributes(typeof(DisplayAttribute), false);
if (attr.Length > 0)
{
// TODO: Call add with expression?
}
}
解决方案
Expression
您可以使用类上的方法相当容易地实现这一点。首先,使用 lambda(例如Expression<Func<A, B>> expr = x => x.PropertyA
)编写表达式是最简单的,然后在调试器中检查它以查看编译器构造什么。
在你的情况下,这样的事情应该有效:
// The parameter passed into the expression (myClassRef) in your code
var parameter = Expression.Parameter(typeof(T), "myClassRef");
// Access the property described by the PropertyInfo 'prop' on the
// myClassRef parameter
var propertyAccess = Expression.Property(parameter, prop);
// Since we're returning an 'object', we'll need to make sure we box value types.
var box = Expression.Convert(propertyAccess, typeof(object));
// Construct the whole lambda
var lambda = Expression.Lambda<Func<T, object>>(box, parameter);
tableDefinition.add(lambda);
请注意,我传递的是Expression<Func<T, object>>
into add
,而不是Expression<Func<T, TValue>>
. 我猜这没关系,它避免了add
使用反射调用。当我编写与add
过去类似的方法时,我根本不在乎TValue
:我只是检查Expression
并PropertyInfo
从属性访问中获取。
如果您确实需要通过 an Expression<Func<T, TValue>>
,则必须执行以下操作:
var delegateType = typeof(Func<,>).MakeGenericType(typeof(T), prop.PropertyType);
var lambda = Expression.Lambda(delegateType, propertyAccess, parameter);
// I'm assuming that your `add` method looks like:
// void add<T, TValue>(Expression<Func<T, TValue>> expr)
// I'm also assuming there's only one method called 'add' -- be smarter in that
// 'GetMethod' call if not.
var addMethod = typeof(TableDefinition)
.GetMethod("add")
.MakeGenericMethod(typeof(T), prop.PropertyType);
addMethod.Invoke(tableDefinition, new object[] { lambda });
Expression.Convert(..., typeof(object))
请注意,在这种情况下您不需要。
推荐阅读
- javascript - 从动态添加的组件中调用宿主或父组件的方法的正确方法是什么?
- html - 如何在中心“div”和“a”元素对齐
- ubuntu-18.04 - ROS 节点正在运行但某些连接断开
- javascript - TypeScript 客户端使用
- java - 如何使 KeyListener 起作用?
- c - C 中在 if 条件下带有括号的问题
- c++ - CRAN 是否需要为包中的每个 .R 和 .cpp 函数提供单独的文件?
- sql-server - 我希望将表 2 中的一些数据和一些常量插入表 1
- python - UnboundLocalError:赋值前引用的局部变量——添加为全局变量?
- c++ - 如何停止/中断当前循环(序列)以运行新数据(序列)?