【发布时间】:2016-10-02 20:13:28
【问题描述】:
简介
我正在使用委托来传递和存储单个表单Controls 的样式逻辑。例如,我有一个包含一些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 可能是什么。
情况
在初始化并存储所有样式后,必须应用样式(使用StyleDels)。为此,我创建了一个函数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);
}
}
StyleDels 使用下面的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>?
【问题讨论】:
-
你能把代理第一次添加到字典中的代码贴出来吗?
-
你是怎么调用这个方法的?无论是隐式还是显式,您都使用
T作为Control调用。 -
我会说问题在于您将委托添加到字典的位置,例如,以下内容有效:
_dict.Add(typeof(Button), (StyleDel<Button>)((Button b) => b.AutoEllipsis = true)); -
@Abion47 我已将该代码放入问题中
-
@Duncan 是的,就是这样。您得到的结果与将泛型替换为
Control相同。在不使用反射调用委托的情况下如何解决它并不是很明显。
标签: c# generics casting delegates