views:

169

answers:

3

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.

+5  A: 

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.

SLaks
My class that stores the list will not have a generic type, However the T in MyObject<T> is known at compile time and the namespace for these objects are referenced in this class. When I try your first example it says The type T must be a reference type in order to use it as a parameter. I want T to be a generic type so I can pass in any datatype, whether it be int, string, etc
Chris Klepeis
You need to add a `where T : class` contstraint, to match the constraint in `MyObject`.
SLaks
Got it... had to add public bool Exists<T>() where T : class .... thanks!
Chris Klepeis
A: 

Since they all implement the same interface, instead of casting them to object and calling GetType (which can be expensive) why not add a property to your interface called class name (or something)? Then you can use the linq in order to grab that property. And don't forget using System.Linq

using System.Linq;

public bool Exist(List<IMyInterface> objects, IMyInterface typeToCheck)
{
   return objects.Any(t => t.ObjectName == typeToCheck.ObjectName);
}
Nate Noonen
My interface is IMyInterface<T>
Chris Klepeis
+1  A: 

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));
}
Dan Tao