在C#中将委托转换为泛型委托

邓肯·卢克

介绍

我正在使用委托来传递和存储单个表单Controls的样式逻辑例如,我有一个包含一些Button如下样式逻辑的委托

button.BackColor = Color.Red;
button.ForeColor = Color.White;
button.FlatStyle = FlatStyle.Flat;

当然,还有许多其他类型的控件,例如Labels,Panels等。因此,为了存储所有这些委托,我使用了Dictionary<Type, Delegate>

虽然,委托本身看起来像这样:

delegate void StyleDel<in T>(T control) where T : Control;

因此,为了使用字典中的逻辑,Delegate必须首先将其强制转换为StyleDel<T>-T当时可能是这样。


情况

在初始化并存储所有样式之后,必须应用样式(使用StyleDels)。为此,我做了一个功能StyleControl(control)

该函数查看控件的类型(例如a Button),然后StyleDel从中找到相应的控件Dictionary,然后依次应用(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使用以下Add功能s添加到字典中:

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抛出an ,表示StyleDel<Button>无法将转换为StyleDel<Control>因此,我相信这TControl在此时其视为,而实际上是一个Button

如何Delegate将其StyleDel<Button>成功投放

中间

您可以通过添加独立级别来实现此目的;创建一个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;
}

乍一看,这似乎不是类型安全的,但是在这种特殊情况下,这是因为将委托存储在字典中,并且将参数的真实类型作为键。因此,按预期使用将始终确保始终使用正确键入的参数调用委托,并且不会发生运行时强制转换异常。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章