Saeid
Saeid

Reputation: 13592

Get type of T in IEnumerable<T>

This is My Generic Class:

public class MyClass<T>
{
    public T MainModel { get; set; }

    public Type GetType()
    {
        //here
    }
}

Then I use it this form:

List<MySecondClass> Myinstance = new List<MySecondClass>();

MyClass<IEnumerable<MySecondClass>> mainInstance = new  MyClass<IEnumerable<MySecondClass>> { MainModel = Myinstance  };

So I need the GetType() Method returned typeof(MySecondClass) what is your suggestion?

Update

I must mention that always use the MyClass in just two form: First : I exactly coded in above and Second:

ThirdClass thirdone = new ThirdClass(); 
MyClass<ThirdClass> = new MyClass<ThirdClass>(){ MainModel = thirdone};

Upvotes: 2

Views: 2778

Answers (3)

Stefan Steinegger
Stefan Steinegger

Reputation: 64648

Consider that IEnumerable<T> is used in many different cases.

Examples:

  • MyClass<IEnumerable<MySecondClass>>: as you said, you want MySecondClass
  • MyClass<List<MySecondClass>>: you probably want MySecondClass
  • MyClass<Dictionary<Guid, MySecondClass>>: Also MySecondClass? Or KeyValuePair<Guid, MySecondClass>?
  • MyClass<MyOwnStringList>: MyOwnStringList would implement IEnumerabl<string>. There is no generic argument on the class itself. There are many examples of that.
  • MyClass<string>: Did you consider that string implements IEnumerable<char>?
  • A class can implement more than one IEnumerable<T> definition.

After considering these cases, you have to decide what to do.

  • You may search for the IEnumerable<T> interface and extract the generic argument. There may be more then one. There may be an exception for strings.
  • You may give up trying to get the IEnumerable<T> generic argument.
  • You may only want to support IEnumerable<T> directly (no subtypes) and, for instance, IList<T>.

Upvotes: 0

Jon
Jon

Reputation: 437804

If T is List<T>

// add error checking to taste
var typeOfEnumerable = typeof(T).GetInterfaces().Where(i => i.IsGenericType)
    .Single(i => i.GetGenericTypeDefinition() == typeof(IEnumerable<>))
    .GetGenericArguments().First();

See it in action.

If T is IEnumerable<T>

// add error checking to taste
var typeOfEnumerable = typeof(T).GetGenericArguments().First();

Important notes

You really should think about what MyClass is trying to do here. Why does it want to special-case for T being an IEnumerable<X>? Perhaps some constraints should be added on T? It's not possible to answer these and other important questions without more concrete information, but you really should do so.

Also, did you name the method GetType by accident or on purpose? It's really, really, really not a good idea to hide object.GetType like that, so I would suggest you rename that method.

Upvotes: 6

Avner Shahar-Kashtan
Avner Shahar-Kashtan

Reputation: 14700

EDIT: Read too fast. Sorry about that.

var t = typeof(T);
if (t.IsGenericType)
{
    return t.GetGenericArguments().FirstOrDefault();
}

Upvotes: 2

Related Questions