在 C# 中将委托强制转换为泛型委托
本文关键字:转换 泛型 | 更新日期: 2023-09-27 18:11:23
简介
我正在使用委托来传递和存储单个表单Control
样式逻辑。例如,我有一个委托,其中包含一些Button
样式逻辑,如下所示:
button.BackColor = Color.Red;
button.ForeColor = Color.White;
button.FlatStyle = FlatStyle.Flat;
当然,还有许多不同类型的控件,如标签、面板等。因此,为了存储所有这些委托,我使用Dictionary<Type, Delegate>
。
虽然,委托本身看起来像这样:
delegate void StyleDel<in T>(T control) where T : Control;
因此,为了使用字典中的逻辑,必须首先将Delegate
转换为StyleDel<T>
- 无论当时T
是什么。
A. 情况
初始化并存储所有样式后,必须应用样式(使用 StyleDel
s(。为此,我做了一个函数StyleControl(control)
.
这个函数查看控件的类型(例如Button
(,并从Dictionary
中找到相应的StyleDel
,而又应用(Button
-(样式。
public void StyleControl<T>(T control) where T : Control
{
Delegate storedDel;
if (_dict.TryGetValue(control.GetType(), out storedDel))
{
// Cast Delegate to StyleDel
var styleDel = (StyleDel<T>) storedDel;
// Execute StyleDel
styleDel(control);
}
}
StyleDel
s 通过下面的Add
函数添加到字典中:
public bool Add<T>(StyleDel<T> styleDel) where T : Control
{
var inDict = _dict.ContainsKey(typeof(T));
if (!inDict) _dict[typeof(T)] = styleDel;
return !inDict;
}
StyleControl
函数由另一个函数调用,该函数确保所有内容都以递归方式设置样式:
public void Style<T>(T parent) where T : Control
{
StyleControl(parent);
// The problem might have to do with this
foreach (Control child in parent.Controls) Style(child);
}
问题所在
抛出InvalidCastException
,说StyleDel<Button>
不能转换为StyleDel<Control>
。所以我相信这是在说T
在这一点上被视为一种Control
,而实际上它是一个Button
。
如何成功地将此Delegate
转换为StyleDel<Button>
?
您可以通过添加不固定级别来实现此目的; 创建一个 lambda,该 lambda 调用您的委托将参数转换为正确的类型:
Dictionary<Type, StyleDel<Control>> _dict = ...
public bool Add<T>(StyleDel<T> styleDel) where T : Control
{
var inDict = _dict.ContainsKey(typeof(T));
if (!inDict) _dict[typeof(T)] = d => StyleDel((T)d);
return inDict;
}
乍一看,这似乎不是类型安全的,但在这种特殊情况下,这是因为委托存储在字典中,参数的真实类型作为键。因此,预期用法将始终确保始终使用正确类型的参数调用委托,并且不会发生运行时强制转换异常。