C# 如何使用表达式设置属性值?
根据以下方法:C# 如何使用表达式设置属性值?,c#,linq,expression,C#,Linq,Expression,根据以下方法: public static void SetPropertyValue(object target, string propName, object value) { var propInfo = target.GetType().GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | Bind
public static void SetPropertyValue(object target, string propName, object value)
{
var propInfo = target.GetType().GetProperty(propName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
if (propInfo == null)
throw new ArgumentOutOfRangeException("propName", "Property not found on target");
else
propInfo.SetValue(target, value, null);
}
您将如何编写它的启用表达式的等价物,而不需要为目标传递额外的参数
我能听到你说,为什么不直接设置属性呢。例如,假设我们有一个具有公共getter但私有setter的属性的类:
public class Customer
{
public string Title {get; private set;}
public string Name {get; set;}
}
我想打电话:
var myCustomerInstance = new Customer();
SetPropertyValue<Customer>(cust => myCustomerInstance.Title, "Mr");
var myCustomerInstance=new Customer();
SetPropertyValue(cust=>myCustomerInstance.Title,“Mr”);
下面是一些示例代码
public static void SetPropertyValue<T>(Expression<Func<T, Object>> memberLamda , object value)
{
MemberExpression memberSelectorExpression;
var selectorExpression = memberLamda.Body;
var castExpression = selectorExpression as UnaryExpression;
if (castExpression != null)
memberSelectorExpression = castExpression.Operand as MemberExpression;
else
memberSelectorExpression = memberLamda.Body as MemberExpression;
// How do I get the value of myCustomerInstance so that I can invoke SetValue passing it in as a param? Is it possible
}
publicstaticvoid SetPropertyValue(表达式memberLamda,对象值)
{
MemberExpression memberSelectorExpression;
var selectorExpression=memberLamda.Body;
var castExpression=选择或表达为一元表达式;
if(castExpression!=null)
memberSelectorExpression=castExpression。操作数作为MemberExpression;
其他的
memberSelectorExpression=memberLamda.Body作为MemberExpression;
//如何获取myCustomerInstance的值,以便调用SetValue并将其作为参数传入?是否可能
}
有什么建议吗 通过扩展方法,你可以作弊,让生活更轻松:
public static class LambdaExtensions
{
public 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);
}
}
}
}
这之所以更容易,是因为您已经有了调用扩展方法的目标。此外,lambda表达式是一个没有闭包的简单成员表达式。在最初的示例中,目标是在闭包中捕获的,要到达底层目标和
PropertyInfo
为什么要这样做?如果属性有一个私有setter,那么就不能从对象外部更改它!您提议的函数破坏了程序的语义。@VladislavZorov我可以看到这样的评论,我同意您的观点。在这种情况下,第三方DTO需要在单元测试中启动,这是最简单的方法。反射也有它的用途。Property.SetValue的可能副本是反射。你不应该使用它。这似乎不适用于嵌套对象,你知道我如何解决这个问题吗?你可以对值类型使用泛型类型:publicstaticvoidsetpropertyvalue(这个t目标,表达式memberLamda,TValue值){var memberSelectorExpression=memberLamda.Body作为MemberExpression;if(memberSelectorExpression!=null){var property=memberSelectorExpression.Member作为PropertyInfo;if(property!=null){property.SetValue(target,value,null)}}
我在答案中加入了@pinus.acer的评论,因为它对我很有效。@Mboros:那么使用反射有什么不对?如果你进行了数百万次操作,可能速度很慢,但偶尔。。。
var myCustomerInstance = new Customer();
myCustomerInstance.SetPropertyValue(c => c.Title, "Mr");