.NET 2.0 için, tam olarak ne istediğinizi yapan ve herhangi bir mülk için çalışan güzel bir kod parçası Control
:
private delegate void SetControlPropertyThreadSafeDelegate(
Control control,
string propertyName,
object propertyValue);
public static void SetControlPropertyThreadSafe(
Control control,
string propertyName,
object propertyValue)
{
if (control.InvokeRequired)
{
control.Invoke(new SetControlPropertyThreadSafeDelegate
(SetControlPropertyThreadSafe),
new object[] { control, propertyName, propertyValue });
}
else
{
control.GetType().InvokeMember(
propertyName,
BindingFlags.SetProperty,
null,
control,
new object[] { propertyValue });
}
}
Buna şöyle deyin:
// thread-safe equivalent of
// myLabel.Text = status;
SetControlPropertyThreadSafe(myLabel, "Text", status);
.NET 3.0 veya üstünü kullanıyorsanız, yukarıdaki yöntemi Control
sınıfın bir uzantı yöntemi olarak yeniden yazabilirsiniz;
myLabel.SetPropertyThreadSafe("Text", status);
GÜNCELLEME 05/10/2010:
.NET 3.0 için bu kodu kullanmalısınız:
private delegate void SetPropertyThreadSafeDelegate<TResult>(
Control @this,
Expression<Func<TResult>> property,
TResult value);
public static void SetPropertyThreadSafe<TResult>(
this Control @this,
Expression<Func<TResult>> property,
TResult value)
{
var propertyInfo = (property.Body as MemberExpression).Member
as PropertyInfo;
if (propertyInfo == null ||
!@this.GetType().IsSubclassOf(propertyInfo.ReflectedType) ||
@this.GetType().GetProperty(
propertyInfo.Name,
propertyInfo.PropertyType) == null)
{
throw new ArgumentException("The lambda expression 'property' must reference a valid property on this Control.");
}
if (@this.InvokeRequired)
{
@this.Invoke(new SetPropertyThreadSafeDelegate<TResult>
(SetPropertyThreadSafe),
new object[] { @this, property, value });
}
else
{
@this.GetType().InvokeMember(
propertyInfo.Name,
BindingFlags.SetProperty,
null,
@this,
new object[] { value });
}
}
daha temiz, daha basit ve daha güvenli bir sözdizimi sağlamak için LINQ ve lambda ifadelerini kullanan:
myLabel.SetPropertyThreadSafe(() => myLabel.Text, status); // status has to be a string or this will fail to compile
Özellik adı artık derleme zamanında denetlenmiyor, aynı zamanda mülkün türü de, bu nedenle (örneğin) bir boolean özelliğine bir dize değeri atamak ve dolayısıyla bir çalışma zamanı istisnasına neden olmak imkansız.
Ne yazık ki bu kimsenin bir başkasının Control
mülkünü ve değerini geçirmek gibi aptalca şeyler yapmasını engellemez , bu nedenle aşağıdakiler mutlu bir şekilde derlenir:
myLabel.SetPropertyThreadSafe(() => aForm.ShowIcon, false);
Bu nedenle, pass-in özelliğinin gerçekten ait olduğundan emin olmak için çalışma zamanı denetimlerini ekledim Control
yöntemin çağrıldığına . Mükemmel değil, ama yine de .NET 2.0 sürümünden çok daha iyi.
Herhangi birinin derleme zamanı güvenliği için bu kodu nasıl geliştireceği hakkında başka önerileri varsa, lütfen yorum yapın!