2009-08-04 65 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");