Jon H
Jon H

Reputation: 1071

Derived Types and Generics

I have a type that uses generics. Let's call it FlowerDescriptor<T> some flowers are described using numbers, others using strings etc.

so FlowerDescriptor<int>; FlowerDescriptor<string>; etc

I want a mechanism (probably extension methods) for doing 2 things

I.e.

equally I might derive from FlowerDescriptor<int> i.e. class NumberedFlower: FlowerDescriptor<int>

new NumberedFlower.GetType().IsFlowerDesriptor == true;

I have played about with variations of IsAssignableFrom and it feels like that ought to work with typeof(FlowerDescriptor<>).IsAssignableFrom(typeof(FlowerDescriptor<string>))

but it doesn't work. If it add the generic type however it does.

I am currently exploring GetInterfaces to know available interfaces. It'd be great to actually understand what I am doing wrong too..

Upvotes: 4

Views: 95

Answers (4)

Jonesopolis
Jonesopolis

Reputation: 25370

You might consider having a non-generic base class. Then your structure could look like:

public abstract class FlowerDescriptor { }

public class FlowerDescriptor<T> : FlowerDescriptor { }

public class NumberedFlower : FlowerDescriptor<int> { }

Your 2 extensions would be:

public static class Extensions
{
    public static bool IsFlowerDescriptor(this object o)
    {
        return o is FlowerDescriptor;
    }

    public static Type GetFlowerDescriptor<T>(this FlowerDescriptor<T> o)
    {
        return typeof (T);
    }
}

and you'd use it like:

public static void Main()
{
    Console.WriteLine(new NumberedFlower().IsFlowerDescriptor());  //true
    Console.WriteLine(new NumberedFlower().GetFlowerDescriptor()); //System.Int32
}

Generics have an adverse effect when it comes to reflecting over and comparing types, because a FlowerDescriptor<int> is a different type from FlowerDescriptor<string>. This is something I have not found a good rhythm for.

Upvotes: 0

Buh Buh
Buh Buh

Reputation: 7545

Here is how you would get those two values:

bool isFlowerDescriptor = x is FlowerDescriptor<object>;

Type descriptorType = x.GetType().GetGenericArguments()[0];

You could wrap these in extension methods if you like. And add null-checks etc.

Upvotes: 0

Paul Swetz
Paul Swetz

Reputation: 2254

I would not expect the string or int class to know if its a descriptor, it makes a lot more sense to get that information from the FlowerDescriptor.

That being said if you want to use reflection you could get the generic type definition from the FlowerDescriptor instance

FlowerDescriptor<int> f = new FlowerDescriptor<int>();
Type t = f.GetType();
Type[] typeArguments = t.GetGenericArguments();
//check if type you care about is in typeArguments

Upvotes: 2

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391286

Unless you want to add interfaces into the mix, the only choice you have is to

  1. Detect that the type is actually a FlowerDescriptor<T>
  2. or detect that the type inherits from something that is a FlowerDescriptor<T>

Unfortunately I don't think you can use IsAssignableFrom when it comes to open generics which means we're left with walking the inheritance chain up to the base classes.

Here is an example piece of code that would do the right thing:

public static bool IsFlowerDescriptor(this Type type)
{
    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(FlowerDescriptor<>))
        return true;
    if (type.BaseType != null)
        return type.BaseType.IsFlowerDescriptor();

    return false;
}

Here's a .NET Fiddle you can experiment with.

Upvotes: 4

Related Questions