tags:

views:

996

answers:

1

I have an interface as follows:

public interface ITestCase<T> where T : HtmlControl
{
    IEnumerable<T> Execute(Manager manager);
}

HtmlControl is a base class from a 3rd party assembly.

I have two implementations of this interface.

One of them is returning null (specified by me), until I nail the logic required (not a difficult task).

The problem is, I call this 2nd implementation from my form's codebehind:

var LoginJuniper = new Login<ArtOfTest.WebAii.Controls.HtmlControls.HtmlDiv>();
LoginProcedure.Login(textBox1.Text, new Test1());

The Login class, and all other classes, take the same type constraint argument (where T is HtmlControl, and all of them from the 3rd party API).

Also, the other issue I ran into is when I use multiple type constraints; is it possible to say T can be one of either or any multiple of these constraints? E.g. if I have:

<T> where T : HtmlControl, IElement

Can I pass in any type which may be an implementation of IElement and not HtmlControl, or vice versa? Via just the 1 interface. This would be quite useful as I wanted to pass in more types to my generic type constraint because the inteface and test cases I derive from the interface can test more than just the HtmlControls classes (can also test IElements implementations as in the 3rd party API this allows me to get screenshots and I would like to test these screenshots (get pixels, assert that the colour is correct)).

Thanks

A: 

I am unsure what exactly you want the answer to (maybe you could try summing up your actual questions).

However in the case of using multiple constraint types, the MSDN doc says:

By constraining the type parameter, you increase the number of allowable operations and method calls to those supported by the constraining type and all types in its inheritance hierarchy. Therefore, when you design generic classes or methods, if you will be performing any operation on the generic members beyond simple assignment or calling any methods not supported by System.Object, you will have to apply constraints to the type parameter.

Which basically means object T must implement all the constraints you are supplying. So you cannot use the method on a type that is not derived from HtmlControl and implements IElement.

There is a way around this, however it is not pretty, and you might aswell split things up. But you could do this:

void Foo<T>(T arg)
{
  if (arg is IElement)
  {
    var argAsIElement = arg as IElement;

    // Do something with argAsIElement
  }
  if (arg is HtmlControl)
  {
    var argAsHtmlControl = arg as HtmlControl;

    // Do something with argAsHtmlControl
  }
}
Yannick M.
Another solution is to create an implementation of IElement that wraps a HtmlControl (an adapter) and use that with a T : IElement constraint in the method
thecoop