How can I work with Type.IsAssignableFrom not working with legacy interfaces?
I made a test case to illustrate the problem I was facing.
The first statement passes, but the second and third don't.
Is there a way to test either of the two unsuccessful k conditions in a different way that will work? It would be nice if it wasn't very fast as I intend to cache the results based on each type.
public interface IParentInterface
{
}
public interface IChildInterface : IParentInterface
{
}
public class ParentClass<T> where T: IParentInterface
{
}
public class ChildClass : ParentClass<IChildInterface>
{
}
public class TestClass
{
public ChildClass Property { get; set; }
}
[TestFixture]
public class ScratchPad
{
[Test]
public void Assignabl()
{
var tc = new TestClass();
var tct = tc.GetType();
var pi = tct.GetProperty("Property");
Assert.IsNotNull(pi);
Assert.IsTrue(typeof(ParentClass<IChildInterface>).IsAssignableFrom(pi.PropertyType));
Assert.IsTrue(typeof(ParentClass<>).IsAssignableFrom(pi.PropertyType));
Assert.IsTrue(typeof(ParentClass<IParentInterface>).IsAssignableFrom(pi.PropertyType));
}
}
By design, your second statement fails. When you write
public class ParentClass<ParentInterface>
it actually means that "ParentInterface" is now the symbol for the type argument (which makes it so confusing that it really confuses you completely). Recording
public class ChildClass : ParentClass<ChildInterface>
then sets an argument of type yout (yes, the one called ParentInterface) for the ChildInterface type. Hence, Childclass is only assigned to ParentClass <ChildInterface>.
Finally, you should make sure that you follow the conventions when defining type arguments, this will confuse you a lot less, for example.
public class ParentClass<T>
Labeling interfaces with "I" will also greatly improve understanding, for example.
interface IParent { }
interface IChild : IParent { }
I suspect that what you want is not possible until we get C # 4.0:
Parent<IChild>
not assigned
Parent<IParent>
There is currently no co / contravariance for generics.
source to share
Is this covariance / contravariance ?
Then it's just something C # currently doesn't support, but C # 4.0 can.
source to share
You can't, because C # 3.0 doesn't support this type of variance. In C # 4.0, you should be able to.
Using another example, let's say you have List<ParentInterface>
it and it can assign it List<ChildInterface>
:
List<ParentInterface> parentList = List<ParentInterface>();
List<ChildInterface> childList = parentList;
The problem is that the internal storage for parentList
is type ParentInterface
. If you got a different interface from ChildInterface
:
public interface ParentInterface2 : ChildInterface {}
And then tried to add it in childList
like this:
childList.Add(new ParentInterface2Implementation());
You will get an exception because it childList
really is List<ParentInterface>
and can only store versions ParentInterface
that are ParentInterface2
not.
source to share