2

Okay so I have a class containing multiple properties of type List.

Some of the lists are just simple types like string, int etc. But some are lists of custom types like Feature, Trailer, Artwork etc.

public class Movie : IMedia
{
   public List<Feature> Features;
   public List<Artwork> Artwork;
   public List<string> Genres;
}

All the custom types (and the Movie class itself) implement the interface IMedia.

Using reflection I want to traverse the Movie properties and do something with those that is of type List<IMedia> - but here lies the problem; Because apparently I can't just use is List<IMedia> when also wanting to specify the property to be of a specific type like List<Feature>.

How would you guys suggest I go about identifying these types?

Extend List<T> itself or something completely different?

Martin Dandanell
  • 831
  • 1
  • 7
  • 20
  • You should show your code. We cannot possibly know what went wrong without your code. – nvoigt Sep 07 '14 at 12:21
  • Do you want to identify the types of the lists or the types of the elements inside the lists? – Theodoros Chatzigiannakis Sep 07 '14 at 12:21
  • Sounds like a textbook use case for an extension class, out of curiosity though `is List` or `.GetType() == TypeOf(List)` should work unless you explicitly recast the class, and if the classes are so familiar and only differing in name why can the object that differentiates them be stored as an object inside the class? – Wobbles Sep 07 '14 at 12:23
  • thats just a combination of http://stackoverflow.com/questions/557340/how-to-get-the-type-of-t-from-a-generic-listt http://stackoverflow.com/questions/4963160/how-to-determine-if-a-type-implements-an-interface-with-c-sharp-reflection – Nahum Sep 07 '14 at 12:27
  • I wouldn't recommend you to use reflection in simple BL cases. It seems to be an overgeneralization. I.e. implement public method which returns IList for some conditions. – Valentin P. Sep 07 '14 at 12:27
  • Really, your code should be refactored so that there is a defined scope where you want to treat all objects as `IMedia`, so you would only need IEnumerable "lists". You'll have to post code to work it out. – Keith Payne Sep 07 '14 at 12:29
  • @TheodorosChatzigiannakis My initial thought was to identify the elements inside the lists, but I guess one could argue for the opposite, right? – Martin Dandanell Sep 08 '14 at 08:15

3 Answers3

3

To get the type of the first generic argument:

var lst = new List<MyClass>();
var t1 = lst.GetType().GenericTypeArguments[0];

To check if you can cast it to an interface:

bool b = typeof(IInterface).IsAssignableFrom(t1);

Another approach could be:

var castedLst = lst.OfType<IInterface>().ToList();
bool b = castedLst.Count == lst.Count; // all items were casted successfully
SimpleVar
  • 14,044
  • 4
  • 38
  • 60
  • Thanks @Yorye Nathan, your answer helped me a lot and it was very close to want I needed, but I accepted Andrews answer as he provided the complete context. – Martin Dandanell Sep 08 '14 at 08:30
3

Assuming you're actually working with properties (which is what's mentioned in the question) and not private fields (which is what the class in your question is using), you could do something like this:

var movie = new Movie() { ... };

foreach (var prop in typeof(Movie).GetProperties())
{
    if (prop.PropertyType.IsGenericType && 
        prop.PropertyType.GetGenericTypeDefinition() == typeof (List<>))
    {
        /* Get the generic type parameter of the List<> we're working with: */
        Type genericArg = prop.PropertyType.GetGenericArguments()[0];

        /* If this is a List of something derived from IMedia: */
        if (typeof(IMedia).IsAssignableFrom(genericArg))
        {
            var enumerable = (IEnumerable)prop.GetValue(movie);

            List<IMedia> media = 
                enumerable != null ? 
                enumerable.Cast<IMedia>().ToList() : null;

            // where DoSomething takes a List<IMedia>
            DoSomething(media);
        }
    }
}
Andrew Whitaker
  • 124,656
  • 32
  • 289
  • 307
-2

If I understood you correctly you have to do something like this:

Type paramType = typeof(T);
if(paramType is IMedia) { /*do smt*/ }
mykhailovskyi
  • 680
  • 1
  • 8
  • 19