c# - 如何使用表达式为索引器设置属性值?
问题描述
我目前有点坚持将值设置为传递给以下函数的索引器表达式:
private static void SetPropertyValue<T, TValue>(this T target, Expression<Func<T, TValue>> memberLamda, TValue value)
{
var memberSelectorExpression = memberLamda.Body as MemberExpression;
if (memberSelectorExpression != null)
{
var property = memberSelectorExpression.Member as PropertyInfo;
if (property != null)
{
property.SetValue(target, value, null);
return;
}
}
}
我有以下课程
class Entity
{
public object this[string name]
{
get { /* */ }
set { /* */ }
}
}
当我现在使用以下值调用先前定义的函数时,我只得到对支持get_Item()
方法的引用:
var entity = new Entity();
// ...
SetPropertyValue(entity, x => x[memberName], value);
有人对我有提示,如何解决这个问题?任何想法都会有所帮助。
非常感谢你们所有人...
解决方案
我想我看到了您正在尝试的内容 - 适用于常规和索引属性的单个SetPropertyValue
扩展。在这种情况下,您需要确定传入的引用类型Expression
以确定如何调用SetValue
:
public static void SetPropertyValue<T, TValue>(this T target, Expression<Func<T,TValue>> memberFn, TValue value) {
var b = memberFn.Body;
if (b is MethodCallExpression bc && bc.Method.IsSpecialName && bc.Method.Name.StartsWith("get_")) {
var PI = typeof(T).GetProperty(bc.Method.Name.Substring(4));
PI.SetValue(target, value, bc.Arguments.Select(a => a.Evaluate<object>()).ToArray());
}
else if (b is MemberExpression bm) {
var pi = bm.Member;
pi.SetValue(target, value);
}
}
您可以通过多种不同的方式确定索引属性名称,我决定假设一个特殊名称以 开头,get_
后跟索引属性名称(当前 C# 编译器使用Item
)并使用它来查找属性。如果编译器更改了名称模式,(例如Item_get
)我看不到方法的 和它所代表的属性之间有任何关系MethodInfo
,get
因此您将不得不重新编写此代码,但这始终是反射的危险。也许寻找名称包含在 get 方法名称中的属性会稍微健壮一些,但速度会慢一些。
这是执行此操作的版本:
public static void SetPropertyValue<T, TValue>(this T target, Expression<Func<T,TValue>> memberFn, TValue value) {
var b = memberFn.Body;
if (b is MethodCallExpression bc && bc.Method.IsSpecialName) {
var PI = typeof(T).GetProperties().First(pi => bc.Method.Name.Contains(pi.Name));
PI.SetValue(target, value, bc.Arguments.Select(a => a.Evaluate<object>()).ToArray());
}
else if (b is MemberExpression bm) {
var pi = bm.Member;
pi.SetValue(target, value);
}
}
推荐阅读
- android - 如何从 string.xml 中的字符串数组将子项添加到 ExpandableListView?
- javascript - 有问题在角度 6 中设置图像缓存
- python - 在 Python 中将 doc 转换为 docx
- android - 如何使用 Url 中的查询参数在改造 2 中获取数据?
- c# - 如何拆分 CSV 文件
- angular - angular 2 4 5 - 如何在 component.ts 中定义对象变量
- java - 在执行 JUnit 测试用例时减少 Spring & Hibernate 初始化时间
- python - Python Django 不会用旧文件覆盖新上传的文件
- twilio - 在 twilio 中更改来电显示
- android - Native Base 的操作表在顶部