您还可以使用 lambda 表达式的动态评估和反射来设置类的特定属性。从性能的角度来看,这可能不是最佳解决方案,但该方法适用于各种数据类型:
using System;
using System.Linq.Expressions;
using System.Reflection;
public class DataClass
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
public string Prop3 { get; set; }
public int Prop4 { get; set; }
public int? Prop5 { get; set; }
}
public class Test
{
public static void Main()
{
var cls = new DataClass() { Prop1 = null, Prop2 = string.Empty, Prop3 = "Value" };
UpdateIfNotSet(cls, x => x.Prop1, UpdateMethod);
UpdateIfNotSet(cls, x => x.Prop2, UpdateMethod);
UpdateIfNotSet(cls, x => x.Prop3, UpdateMethod);
UpdateIfNotSet(cls, x => x.Prop4, (x) => -1);
UpdateIfNotSet(cls, x => x.Prop5, (x) => -1);
Console.WriteLine(cls.Prop1); // prints "New Value for Prop1"
Console.WriteLine(cls.Prop2); // prints "New Value for Prop2"
Console.WriteLine(cls.Prop3); // prints "Value"
Console.WriteLine(cls.Prop4); // prints "0"
Console.WriteLine(cls.Prop5); // prints "-1"
}
public static void UpdateIfNotSet<TOBJ, TPROP>(TOBJ obj,
Expression<Func<TOBJ, TPROP>> prop,
Func<string, TPROP> updateMth)
{
var currentValue = prop.Compile().DynamicInvoke(obj);
var strValue = currentValue as string; // Need to convert to string gracefully so that check against empty is possible
if (currentValue == null || (strValue != null && strValue.Length == 0))
{
var memberAcc = (MemberExpression)prop.Body;
var propInfo = (PropertyInfo)memberAcc.Member;
propInfo.SetMethod.Invoke(obj, new object[] { updateMth(propInfo.Name) });
}
}
public static string UpdateMethod(string propName)
{
return "New Value for " + propName;
}
}
UpdateIfNotSet 方法需要以下参数:
- 一个对象
- 访问对象属性的 lambda 表达式
- 检索更新值的函数。请注意,该函数在调用时接受一个字符串作为参数,该参数填充属性名称
UpdateIfNotSet 方法的通用参数由编译器推断,因此您不必指定它们。
该方法首先编译 lambda 表达式并通过调用已编译的表达式来检索属性的当前值。然后它检查该值是 null 还是空字符串。在这种情况下,它通过调用提供的方法为属性分配一个新值。