views:

140

answers:

6

I have a System.Collections.Generic.Dictionary<System.Web.UI.Control, object> where all keys can be either type of System.Web.UI.WebControls.HyperLink or type of System.Web.UI.WebControls.Label.

I want to change Text property of each control. Because HyperLink doesn't implement (why??) ITextControl, I need to cast Label or HyperLink explicitly:

Dictionary<Control,object> dic = ..

dic
  .Where(p => p.Key is HyperLink)
  .ForEach(c => ((HyperLink)c).Text = "something")

dic
  .Where(p => p.Key is Label)
  .ForEach(c => ((Label)c).Text = "something")

Are there ways to workaround such approach?

+5  A: 

Slightly more elegant, but retaining the problem:

foreach (HyperLink c in dic.Keys.OfType<HyperLink>())
{
    c.Text = "something";
}

foreach (Label c in dic.Keys.OfType<Label>())
{
    c.Text = "something";
}
dtb
Is it really a problem, though?
Isaac Cambron
@Isaac Cambron: It iterates the collection twice and performs a lot of type checks, so I'd say it's somewhat ugly. My vote is on the solution by @Stefan Egli.
dtb
+2  A: 
dic.ForEach(c => c.Key.GetType()
    .GetProperty("Text")
    .SetValue(c.Key, "Something",null));

Total hack, probably not efficient, but it should work....

EDIT: Another thing worth mentioning, if you're using .Net 4, you can use duck typing:

dic.ForEach(kvp => ((dynamic)kvp.Key).Text = "Something");
BFree
Mutual? Yes. Faster? Hardly.
abatishchev
@abat - ... or in other words "probably not efficient"
John Rasch
-1 Not a good way :(
Oskar Kjellin
+3  A: 

You could create a class that derives from HyperLink and let your class inherit from ITextControl. Should be clear where to go from there...

Stefan Egli
+2  A: 

This way looks uglier and clumsier, but at least you're only enumerating over the dictionary one time:

dic
  .ForEach(
    c => {
      var clink = c as Hyperlink;
      if (clink != null) {
        clink.Text = "something";
        return;
      }

      var clabel = c as Label;
      if (clabel != null) {
        clabel.Text = "something";
        return;
      }
    }
  );
Dan Tao
A: 

Unless the Text is a property of Control, it's more clear if you specify it in separate statements. I wouldn't try to combine them simply because they both use the word "Text" to define the property.

Eugarps
+1  A: 

Same as Dan Tao's answer - just styled for minimum clumsiness.

foreach(Control c in dic.Keys)
{
  HyperLink clink = c as Hyperlink; 
  if (clink != null)
  { 
    clink.Text = "something";
    continue;
  } 

  Label clabel = c as Label; 
  if (clabel != null)
  { 
    clabel.Text = "something";
    continue;
  } 
} 
David B