0

How do I use .NET reflection to get a list of properties that are of a particular class, including generic lists, e.g. I have a class that looks like this:

class Test
{
    [NotConditional()]
    [Order( 1 )]
    public Value Name { get; set; }

    [NotConditional()]
    [Order( 2 )]
    public Value Address { get; set; }

    [NotConditional()]
    [Order( 3 )]
    public List<Value> Contacts { get; set; }
}

I want to get the Name, Address and Contacts properties as all of them are of type Value.

I have the following code, which works great, but I want the List<> bit to only pick up List<Value> properties.

var props = from p in this.GetType().GetProperties()
            where p.PropertyType.IsSubclassOf( typeof( Std ) ) ||
            ( p.PropertyType.IsGenericType &&
              p.PropertyType.GetGenericTypeDefinition() == typeof( List<> ) )
              select new { Property = p };

I have tried:

var props = from p in this.GetType().GetProperties()
            where p.PropertyType.IsSubclassOf( typeof( Std ) ) ||
            ( p.PropertyType.IsGenericType &&
              p.PropertyType.GetGenericTypeDefinition() == typeof( List<Value> ) )
              select new { Property = p };

But, it doesn't pick up any List<Value> properties and only picks up Name and Address properties.

** UPDATE **

I have included these two classes as well as I also want to include properties that also derive from Std'.

class Std
{
    public int id { get; set; }
}

class Value : Std
{
    public string Val { get; set; }
}
4
  • Why are you using GetGenericTypeDefinition when you don't actually want the generic type definition? Commented Jul 25, 2014 at 14:57
  • @JonSkeet That's because I found this code on a Stack Overflow post and used it as it's what I was looking for only that it did'nt pick up the List<Value> properties I also wanted. Commented Jul 25, 2014 at 14:59
  • 2
    In future, it's worth making sure that you thoroughly understand code from elsewhere before using it. I suspect you were looking at code which was trying to find properties of any list type, hence the call to GetGenericTypeDefinition. Commented Jul 25, 2014 at 15:01
  • @JonSkeet That's an excellent lesson to learn. I did understand what the code was doing, but misinterpreted the reasoning of the GetGenericTypeDefinition method call. Commented Jul 25, 2014 at 15:02

1 Answer 1

4

Seems pretty straightforward. Try this:

var props = from p in this.GetType().GetProperties()
            where p.PropertyType == typeof(Value) ||
                  p.PropertyType == typeof(List<Value>)
            select new { Property = p };

Or to handle subclasses of Value or List<Value>

var props = from p in this.GetType().GetProperties()
            where typeof(Value).IsAssignableFrom( p.PropertyType ) ||
                  typeof(List<Value>).IsAssignableFrom( p.PropertyType )
            select new { Property = p };

Given your update, if you want to get any property whose type is assignable from Std or is a list whose parameter is assignable from Std, that's a bit more difficult because List<T> is invariant with respect to T. If that's what you want, you can do something like this:

var props = from p in this.GetType().GetProperties()
            where typeof(Std).IsAssignableFrom( p.PropertyType ) ||
                  ( p.PropertyType.IsGenericType &&
                    p.PropertyType.GetGenericTypeDefinition() == typeof(List<>) && 
                    typeof(Std).IsAssignableFrom( p.PropertyType.GetGenericArguments()[0] ) )
            select new { Property = p };

Note that this version doesn't return properties whose types inherit from List<Std>.

Sign up to request clarification or add additional context in comments.

2 Comments

I am aware of this. A List<Value> is never going to be assigned to a List<Std> but I have other properties that derive from Std and would like them picked up as well as Value classes.
@Mike See my updated answer for an alternative solution that might work in your situation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.