【发布时间】:2011-04-15 19:58:06
【问题描述】:
我正在使用以下代码以线程安全的方式设置Control 属性:
private delegate void SetPropertyThreadSafeDelegate<TPropertyType>(Control @this, Expression<Func<TPropertyType>> property, TPropertyType value);
public static void SetPropertyThreadSafe<TPropertyType>(this Control @this, Expression<Func<TPropertyType>> property, TPropertyType value)
{
var propertyInfo = (property.Body as MemberExpression ?? (property.Body as UnaryExpression).Operand as MemberExpression).Member as PropertyInfo;
if (propertyInfo == null ||
!propertyInfo.ReflectedType.IsAssignableFrom(@this.GetType()) ||
@this.GetType().GetProperty(propertyInfo.Name, propertyInfo.PropertyType) == null)
{
throw new ArgumentException("The lambda expression 'property' must reference a valid property on this Control.");
}
if (propertyInfo.PropertyType.IsValueType &&
!propertyInfo.PropertyType.IsAssignableFrom(typeof(TPropertyType)))
{
throw new ArgumentException(string.Format("Attempted to assign incompatible value type: expecting {0}, got {1}.", propertyInfo.PropertyType, typeof(TPropertyType)));
}
if (@this.InvokeRequired)
{
@this.Invoke(new SetPropertyThreadSafeDelegate<TPropertyType>(SetPropertyThreadSafe), new object[] { @this, property, value });
}
else
{
@this.GetType().InvokeMember(propertyInfo.Name, BindingFlags.SetProperty, null, @this, new object[] { value });
}
}
是这样称呼的:
downloadProgressBar.SetPropertyThreadSafe(() => downloadProgressBar.Step, 32);
这样做的原因是为了在编译时检查属性名称和类型分配。它适用于标准对象,但对于值类型,一切都变得有点像梨形,因为编译器很乐意接受以下内容,这当然会在运行时炸弹:
downloadProgressBar.SetPropertyThreadSafe(() => downloadProgressBar.Step, 'c');
downloadProgressBar.SetPropertyThreadSafe(() => downloadProgressBar.Step, long.MaxValue);
我已经修改了SetPropertyThreadSafe 方法来处理使用值类型时的情况,如果使用不正确的类型作为参数则抛出异常,但我真正在寻找的是能够获得此方法对 100% 的情况执行编译时类型检查,即对象 和 值类型。这甚至可能吗?如果可以,我需要如何修改我的代码才能做到这一点?
【问题讨论】:
标签: c# .net linq lambda expression-trees