Guys,

I've got an issue but I also dont know if its possible. I've templated (generic'd out a class that takes type T where T is a HtmlControl object

...

internal class Controller<T> where T : HtmlControl
        {
            public T locateControl(T t)
            {
                t.SearchProperties.Clear();
                t.Find();
                return t;
            }
        }

this gets called like...

FindControl<HtmlEdit> controllocator = new FindControl<HtmlEdit>();
 HtmlEdit txtEntityName = controllocator.findControl(new HtmlEdit());

... do stuff here

Now what I'm finding is that if I have a new control thats a subclass of HtmlControl I'm having to redefine the FindControl class again with the new type of control. I don't really want to have to do this... Is there a nicer way of tackling it?

For example

FindControl<HtmlEdit> controllocator = new FindControl<HtmlEdit>();
 HtmlEdit txtEntityName = controllocator.findControl(new HtmlEdit());

 FindControl<HtmlLongEdit> controllocator2 = new FindControl<HtmlLongEdit>();
 HtmlEdit txtEntityName = controllocator2.findControl(new HtmlLongEdit());

Why can't I have something like this

FindControl<HtmlEdit> controllocator = new FindControl<HtmlEdit>();
 HtmlEdit txtEntityName = controllocator.findControl(new HtmlEdit());
 HtmlLongEdit txtEntityName = controllocator2.findControl(new HtmlLongEdit());

Recommended Answers

All 3 Replies

When you deal with generics, instances of the class take the type parameter and then it deals with that type. When you call controllocator.findControl(new HtmlEdit()) I assume you are creating an instance of Controller<HtmlEdit> . Since HtmlLongEdit class doesn't extend HtmlEdit, you can't use the same object to call findControl again on this second type. Here's one way to handle it:

Make your Controller class a base, abstract class and extend it like so:

internal abstract class AbstractController<T> where T : HtmlControl
{
  public abstract T locateControl(T t);
}

internal class Controller<HtmlControl> : AbstractController<T>
{
  public override HtmlControl locateControl(HtmlControl t)
  {
    t.SearchProperties.Clear();
    t.Find();
    return t;
  }
}

So now your generics class is taking objects of type HtmlControl. This should allow you to make the calls as you originally wanted since both the HtmlEdit and HtmlLongEdit classes extend HtmlControl.

Okay, but is there a way to cast this out ? Cause otherwise I'd have to cast this to a htmlLongEdit, or a htmlEdit control. Ideally I wanted a class that didn't take anything but then was told what it was looking for.

My example shows one instance of the findControl which as a method that takes a type of HtmlControl. If I could cast the return value of be a type of htmlLongEdit or a htmlEdit.

Wouldn't it be something along the lines of supplying an extra template constraint and then passing that into findControl? Then casting the return?

Class controller

Public E findControl(T t, E e) //where T is of type HTMLControl and E is the type that extends HTML control.

You can use the Type class, or alternatively you can call [object].GetType() on the return value of the call.

Example:

FindControl<HtmlControl> controllocator = new FindControl<HtmlControl>();
HtmlControl txtEntityName = controllocator.findControl(new HtmlControl());
if (txtEntityName.GetType() == typeof(HtmlEdit))
{
   HtmlEdit edit = (HtmlEdit)txtEntity;
}

The downside is that you need a really big if-statement if you have many extending classes.

I think there is a way to do this using reflection, but I haven't really done anything with that before. I think its System.Assembly.Reflection namespace that you want to use, sorry I can't provide an example of this method but Google might provide some.

Good luck :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.