Ed Guiness
Ed Guiness

Reputation: 35287

How can I determine property types using reflection?

How would I test a property of a type to see if it is a specified type?

EDIT: My goal is to examine an assembly to see if any of the types in that assembly contain properties that are MyType (or inherited from MyType).

Here is the track I've gone down...

AssemblyName n = new AssemblyName();
n.CodeBase = "file://" + dllName;
Assembly a = AppDomain.CurrentDomain.Load(n);

foreach (Type t in a.GetTypes())
    foreach (PropertyInfo pi in t.GetProperties())
        if ( pi.PropertyType is MyType ) // warning CS0184
            Console.WriteLine("Found a property that is MyType");

This compiles with warning CS0184: The given expression is never of the provided ('MyType') type

Upvotes: 38

Views: 63146

Answers (8)

This is shortcut way

property.PropertyType.IsGenericType && (typeof(ICollection<>).IsAssignableFrom(property.PropertyType.GetGenericTypeDefinition()))
&& typeof(<YourType>).IsAssignableFrom(property.PropertyType.GenericTypeArguments[0])

Upvotes: 0

PeteGO
PeteGO

Reputation: 5791

You should use is when comparing an instance of something with an explicitly written type:

Department sales = new Department("Sales");

Debug.Assert(sales is Department);

You should use typeof when you want to compare 2 types and you can't write the type explicitly:

private void CheckType(Type t)
{
    Debug.Assert(typeof(Department) == t);
}

Using is will take inheritence into account, typeof wont.

public class Animal { }
public class Dog : Animal { }

public void Test()
{
    Dog d = new Dog();

    Debug.Assert(d is Animal); // true

    Debug.Assert(typeof(Dog) == typeof(Animal); // false
}

If you want to compare 2 types and take inheritence into account, you can use IsAssignableFrom:

Debug.Assert(typeof(Animal).IsAssignableFrom(typeof(Dog))); // true

Upvotes: 0

vlr
vlr

Reputation: 790

This example from the other similar question simplified the understanding for me a lot

If p.PropertyType Is GetType(String) Then

Upvotes: 1

rivy
rivy

Reputation: 1630

There are multiple ways to test an object's type:

1) Use the is operator:

if (anObject is MyType) {
// anObject is MyType or a derived class
... 
}

2) Use the as operator:

MyType newObject = anObject as MyType;
if (newObject != null ) {
// newObject is anObject cast to MyType
...
}

3) Use typeof() and GetType() [3 variations]:

// #1
if (typeof(MyType) == anObject.GetType()) {
// anObject is a MyType
...
}

//#2
public static bool IsType(object obj, string type)
{// modified from Visual C# 2005 Recipes {Apress}
// Get the named type, use case-insensitive search, throw
// an exception if the type is not found.
Type t = Type.GetType(type, true, true);
return t == obj.GetType();
}

//#3
public static bool IsTypeOrSubclass(object obj, string type)
{// modified from Visual C# 2005 Recipes {Apress}
// Get the named type, use case-insensitive search, throw
// an exception if the type is not found.
Type t = Type.GetType(type, true, true);
return t == obj.GetType() || obj.GetType().IsSubclassOf(t);
}

Upvotes: 2

Paolo Tedesco
Paolo Tedesco

Reputation: 57302

I think you need something like this:

using System;
using System.Reflection;

namespace ConsoleApplication1{
    class Class1{

        static bool checkType(Type propertyType,Type myType){
            if (propertyType == myType){
                return true;
            }
            Type test = propertyType.BaseType;
            while (test != typeof(Object)){
                if (test == myType){
                    return true;
                }
                test = test.BaseType;
            }
            return false;
        }

        [STAThread]
        static void Main(string[] args){
            Assembly a = Assembly.GetExecutingAssembly();
            foreach (Type t in a.GetTypes()){
                Console.WriteLine("Type: {0}",t.Name);
                foreach (PropertyInfo p in t.GetProperties()){
                    if (checkType(p.PropertyType,typeof(MyType))){
                        Console.WriteLine("  Property: {0}, {1}",p.Name,p.PropertyType.Name);
                    }
                }
            }
        }
    }

    class MyType{
    }

    class MyType2 : MyType{
    }

    class TestType
    {
        public MyType mt{
            get{return _mt;}
            set{_mt = value;}
        }
        private MyType _mt;
        public MyType2 mt2
        {
            get{return _mt2;}
            set{_mt2 = value;}
        }
        private MyType2 _mt2;
    }
}

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1504002

What type are you interested in? The return type of the method/property/event etc?

If so, I don't think there's anything in MemberInfo to let you get at it directly - you'll need to cast and use MethodInfo.ReturnType, PropertyInfo.PropertyType, FieldInfo.FieldType, EventInfo.EventHandlerType and any others I've forgotten. (Remember that types themselves can be members. Not sure what you'll want to do with them!)

EDIT: If you're interested in whether a specific Type represents either MyType or some subclass, then use Type.IsAssignableFrom:

if (typeof(MyType).IsAssignableFrom(type))

EDIT: Now that we know you want properties, it's easy - use GetProperties instead of GetMembers. I like doing reflection with LINQ:

var query = from type in assembly.GetTypes()
            from property in type.GetProperties()
            where typeof(MyType).IsAssignableFrom(property.PropertyType)
            select new { Type=type, Property=property };

foreach (var entry in query)
{
    Console.WriteLine(entry);
}

If you're not a fan of LINQ:

foreach (Type t in a.GetTypes())
    foreach (PropertyInfo pi in t.GetProperties())
        if (typeof(MyType).IsAssignableFrom(pi.PropertyType))
            Console.WriteLine("Found a property that is MyType");

Note that you might want to specify binding flags to get non-public properties etc.

Upvotes: 59

BFree
BFree

Reputation: 103770

Ok, maybe I'm missing something stupid, but shouldn't it be:

if ( pi.PropertyType == typeof(MyType ))

???

Upvotes: 48

Alexander
Alexander

Reputation: 3754

You are looking for:

if (typeof(mi) is MyType) { ... }

right ?

Upvotes: 1

Related Questions