忽略是否在您特定的情况下有用(在那种情况下,我认为您所采取的方法很好),您的问题是“是否有一种将属性转换为委托的方法”。
嗯,有可能有。
每个属性实际上(在幕后)由一个或两个方法组成 - 一个设置方法和/或一个获取方法。如果您可以获得这些方法,则可以创建包装它们的委托。
例如,一旦您获得了表示类型为TObj对象的TProp属性的System.Reflection.PropertyInfo对象,我们可以创建一个Action<TObj,TProp>(即,一个接受要设置属性的对象和要设置的值的委托)来包装该setter方法,如下所示:
Delegate.CreateDelegate(typeof (Action<TObj, TProp>), propertyInfo.GetSetMethod())
或者我们可以创建一个Action<TProp>
,将其包装在特定实例的TObj
上,如下所示:
Delegate.CreateDelegate(typeof (Action<TProp>), instance, propertyInfo.GetSetMethod())
我们可以使用静态反射扩展方法来包装这些内容:
Static Reflection。
public static Action<T> GetPropertySetter<TObject, T>(this TObject instance, Expression<Func<TObject, T>> propAccessExpression)
{
var memberExpression = propAccessExpression.Body as MemberExpression;
if (memberExpression == null) throw new ArgumentException("Lambda must be a simple property access", "propAccessExpression");
var accessedMember = memberExpression.Member as PropertyInfo;
if (accessedMember == null) throw new ArgumentException("Lambda must be a simple property access", "propAccessExpression");
var setter = accessedMember.GetSetMethod();
return (Action<T>) Delegate.CreateDelegate(typeof(Action<T>), instance, setter);
}
现在,我可以像这样获取对象属性的“setter”委托:
MyClass myObject = new MyClass()
Action<string> setter = myObject.GetPropertySetter(o => o.Property1)
这是强类型的,基于属性本身的类型,因此在重构和编译时进行类型检查时非常健壮。
当然,在您的情况下,您希望能够使用可能为空的对象设置属性,因此强类型的包装器并不是全部解决方案 - 但它确实为您提供了可传递给SetPropertyFromDbValue
方法的内容。
public static PropertyInfo GetPropertyInfo<T, TProperty>(this Expression<Func<T, TProperty>> expression)
,我能够将其用作另一个库函数的基础之一,以获取Linq to Sql字符串字段的最大长度。谢谢! - Stephen Kennedy