Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# determining generic type

I have several templated objects that all implement the same interface:

I.E.

MyObject<datatype1> obj1;
MyObject<datatype2> obj2;
MyObject<datatype3> obj3;

I want to store these objects in a List... I think I would do that like this:

private List<MyObject<object>> _myList;

I then want to create a function that takes 1 parameter, being a datatype, to see if an object using that datatype exists in my list.... sorta clueless how to go about this. In Pseudo code it would be:

public bool Exist(DataType T)
{
   return (does _myList contain a MyObject<T>?);
}

Some Clarification....

My interface is IMyObject<T>, my objects are MyObject<T>. I have a new class MyObjectManager which I need to have a List of MyObject<T> stored within. I need a function to check if a MyObject<T> exists in that list. The type T are datatypes which were auto-generated using T4.... POCO classes from my Entity Data Model.

like image 980
Chris Klepeis Avatar asked May 27 '10 17:05

Chris Klepeis


2 Answers

You can make a generic function:

public bool Exists<T>() where T : class {
    return _myList.OfType<MyObject<T>>().Any();
}

Note that this requires that you know T at compile-time.

If all you have is a System.Type object at runtime, you'll need to use reflection:

public bool Exists(Type t) {
    var objectOfT = typeof(MyObject<>).MakeGenericType(t);

    return _myList.Any(o => o.GetType() == objectOfT);
}

Note, however, that a List<MyObject<object>> cannot hold a MyObject<SomeType>.
You need to change the list to a List<object>, or make MyObject implement or inherit a non-generic type and make the list contain that type.

like image 189
SLaks Avatar answered Sep 28 '22 02:09

SLaks


How about an extension method?

public static bool HasAny(this IEnumerable source, Type type) {
    foreach (object item in source)
        if (item != null && item.GetType().Equals(type))
            return true;

    return false;
}

Usage:

bool hasDataType1 = myList.HasAny(typeof(MyObject<datatype1>));

Note that if you don't want to have to type out typeof(...) -- i.e., if you basically want your Exist method to only care about objects of type MyObject<T>, I'd go with something like SLaks's answer:

public static bool Exist<T>(this IEnumerable source) {
    return source.OfType<MyObject<T>>().Any();
}

Also, SLaks is right that you really can't have a List<MyObject<object>> that's full of anything other than objects of type MyObject<object> or some derived class (and MyObject<datatype1>, etc. do not derive from MyObject<object> -- generics don't work that way).

Another way I might suggest to work around the whole "you can't get the type of a generic class using a System.Type object without using reflection" issue would be this: Make your MyObject<T> implement a non-generic interface, like this:

public interface IMyObject {
    Type DataType { get; }
}

public class MyObject<T> : IMyObject<T>, IMyObject {
    public Type DataType {
        get { return typeof(T); }
    }
}

Then your list could be a List<IMyObject> (the non-generic interface) and your Exist method could look like this:

public static bool Exist<T>(this IEnumerable source, Type type) {
    return source.OfType<IMyObject>().Any(x => x.DataType.Equals(type));
}
like image 25
Dan Tao Avatar answered Sep 28 '22 01:09

Dan Tao