目前,我有点想将值设置到传递给以下函数的索引器表达式中:
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);
有人对我有提示,如何解决这个问题?任何想法都会有所帮助。
非常感谢大家...
答案 0 :(得分:1)
我想我知道您在尝试什么-单个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);
}
}