2009-08-04 48 views
0

假设我有以下的委托指定一个委托参数

public delegate void ControlInitializer(Control control); 

是否有指定的委托指定输入参数是什么类型的控制时的方式的具体型号?例如

而不是

ControlInitializer one = c => ((TextBox)c).Text = "Init Value" 
ControlInitializer two = c => ((DropDownList)c).SelectedValue= "-1" 

我可以这样做

ControlInitializer one = (TextBox c) => c.Text = "Init Value" 
ControlInitializer two = (DropDownList c) => c.SelectedValue= "-1" 

由于文本框是在这种情况下,一个子类控制的?

更新:我还需要将这2个ControlInitialiser代理存储在例如

Dictionary<string, ControlInitializer> 

会在这种情况下,指定

Dictionary<string, ControlInitializer<Control>> 

工作,因为我似乎无法得到它的工作。

在此先感谢。

+1

您可以使用行动而不是定义自己的委托,如果您使用的.NET Framework 3.5。 – 2009-08-04 12:28:34

+1

`动作`也可以使用.net 2.0以及 – 2009-08-04 13:21:13

回答

10

您可以委托通用:

public delegate void ControlInitializer<TControl>(TControl control) 
    where TControl : Control; 

,然后用它是这样的:

ControlInitializer<TextBox>  one = c => c.Text = "Init Value"; 
ControlInitializer<DropDownList> two = c => c.SelectedValue = "-1"; 

我猜你的目标是这样的:

var init = new Init(); 

init.RegisterInitializer<TextBox>(c => c.Text = "Init Value"); 
init.RegisterInitializer<DropDownList>(c => c.SelectValue = "-1"); 

foreach (var c in Controls) 
{ 
    init.ApplyInitializer(c); 
} 

由于r有点困难easons在中提到David B的回答。你可以做什么,但是,是隐藏施放一个抽象的背后,是这样的类型:

所有的
public class Init 
{ 
    private readonly Dictionary<Type, Action<Control>> initializers; 
    ... 

    public void RegisterInitializer<TControl>(Action<TControl> i) 
     where T Control : Control 
    { 
     initializers.Add(typeof(TControl), c => i((TControl)c)); 
    } 

    public void ApplyInitializer(Control c) 
    { 
     initializers[c.GetType()](c); 
    } 
} 
+0

听起来不错。如果我有一个Dictionary 将这些存储在一个静态变量中,我可以使用Dictionary >进行初始化并添加代表“one”和“two”? – 2009-08-04 14:24:25

+0

不,由于类型协方差 – 2009-08-04 15:09:08

3

首先,使用预定义的委托Action。至于指定类型,使用通用的参数:

Action<TextBox, string> one = (c,v) => c.Text = v; 

Action代表最多需要4个参数,并且不返回任何东西(void)。

2

你不能到ControlInitializer<TextBox>添加到持有ControlInitializer<Control>,因为第一类不从第二类(即使TextBox继承Control。)这是所有关于缺少协变和逆变的继承字典在泛型中。

你可以编写你自己的集合来表现你期望的方式。这里有一个可能性:

public class CustomStorage 
{ 
    private Dictionary<string, object> storage = new Dictionary<string, object>(); 

    public void Remember(string key, object value) 
    { 
    storage[key] = value; 
    } 

    public object Retrieve(string key) 
    { 
    object x = storage[key]; 
    return x; 
    } 

    public U Retrieve<U>(string key) 
    { 
    U u = (U) storage[key]; 
    return u; 
    } 
} 

这可能是这样使用:

CustomStorage cs = new CustomStorage(); 
ControlInitializer<TextBox> one = c => c.Text = "Init Value"; 
ControlInitializer<DropDownList> two = c => c.SelectedValue = "-1"; 
    //drop the items into the collection ... 
cs.remember("TextBox", one); 
cs.remember("DropDownList", two); 
    // ... and fetch them back 
one = cs.Retrieve<ControlInitializer<TextBox>>("TextBox"); 
two = cs.Retrieve<ControlInitializer<DropDownList>>("DropDownList");