Imagine you have a generic class and interface that are defined as follows:
public abstract class MyGenericClass<T>
{
}
public interface IMyGenericInterface<T>
{
}
If you were to derive or implement from the above class/interface, you will find that you cannot use the “is” keyword to determine if that class implements or derives from the above interface. Here is what I mean: If I were to implement/derive from the base class like so:
public class MyInt:MyGenericClass<int>
{
}public class MyInterfacedInt:IMyGenericInterface<int>
{
}
Then I can do the following: (code will run in LinqPad)
MyInt myInt = new MyInt();
MyInterfacedInt myIInt = new MyInterfacedInt();(myInt is MyInt).Dump();//true
(myIInt is MyInterfacedInt).Dump();//true;(myInt is MyGenericClass<int>).Dump();//true
(myIInt is IMyGenericInterface<int>).Dump();//true;
But I cannot do the following:
//Will not compile
//(myInt is MyGenericClass<>).Dump();
//(myInt is IMyGenericInterface<>).Dump();
Why is this important? If you plan on loading plugins at run time, then all you know is that they will implement an interface or a base class and you need to check that. One way around this would be to create a non-generic base class or interface and check against that. But that might not be a possibility if you are using a 3rd party API (eg: Prism and the CompositePresentationEvent<> type).
So here is a helper class that can do just that:
static class ReflectionHelper
{
public static bool IsDerivedOrImplementedFrom<T>(this T objectToCheck, Type parentType) where T : class
{
if (objectToCheck == null)
return false;
if (parentType.IsInstanceOfType(objectToCheck))
return true;bool checkingInterfaces = parentType.IsInterface;
Type toCheck = objectToCheck.GetType();
while (toCheck != null && toCheck != typeof(object)) {
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (checkingInterfaces)
{
bool implementsParentInterface = toCheck.GetInterfaces()
.Any(ci => {
return ci.IsGenericType ? ci.GetGenericTypeDefinition() == parentType :
ci == parentType;
});
if (implementsParentInterface)
return true;
}
else
{
if (parentType == cur)
{
return true;
}
}
toCheck = toCheck.BaseType;
}
return false;
}}
And here is how you call it:
static void Main(string[] args)
{
MyInt myInt = new MyInt();
MyInterfacedInt myIInt = new MyInterfacedInt();"Using the \"is\" keyword".Dump();
(myInt is MyInt).Dump();//true
(myIInt is MyInterfacedInt).Dump();//true;(myInt is MyGenericClass<int>).Dump();//true
(myIInt is IMyGenericInterface<int>).Dump();//true;//Will not compile
//(myInt is MyGenericClass<>).Dump();
//(myInt is IMyGenericInterface<>).Dump();"Using IsDerivedOrImplementedFrom".Dump();
myInt.IsDerivedOrImplementedFrom(typeof(MyInt)).Dump(); //true
myIInt.IsDerivedOrImplementedFrom(typeof(MyInterfacedInt)).Dump();//true
myInt.IsDerivedOrImplementedFrom(typeof(MyGenericClass<int>)).Dump();//true
myIInt.IsDerivedOrImplementedFrom(typeof(IMyGenericInterface<int>)).Dump();//truemyInt.IsDerivedOrImplementedFrom(typeof(MyGenericClass<>)).Dump();//true
myIInt.IsDerivedOrImplementedFrom(typeof(IMyGenericInterface<>)).Dump();//true"Negative tests Using IsDerivedOrImplementedFrom".Dump();
myInt.IsDerivedOrImplementedFrom(typeof(MyInterfacedInt)).Dump(); //false
myIInt.IsDerivedOrImplementedFrom(typeof(MyInt)).Dump();//false
myInt.IsDerivedOrImplementedFrom(typeof(MyGenericClass<string>)).Dump();//false
myIInt.IsDerivedOrImplementedFrom(typeof(IMyGenericInterface<string>)).Dump();//falsemyInt.IsDerivedOrImplementedFrom(typeof(IMyGenericInterface<>)).Dump();//false
myIInt.IsDerivedOrImplementedFrom(typeof(MyGenericClass<>)).Dump();//falseConsole.ReadLine();
}
Here is the full code: http://pastebin.com/raw.php?i=Y2nSQc7V
No comments:
Post a Comment