user1465073
user1465073

Reputation: 335

Dynamic/ Expression based way to get property type of a class?

I currently have a function that gets the type of a property of an object and it can be seen below.

private static Type GetPropertyType<TClass, TResult>(Expression<Func<TClass, TResult>> propertyExpression)
{
    Type type = propertyExpression.Body.Type;
    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
    {
        type = Nullable.GetUnderlyingType(type);
    }
    return type;
}

Now, the problem with this is that i need to have an instance of the object that i intend to get the type of the property as seen below

var baseZoneTypeEntity = zoneTypeCollection.First();
Type t = GetPropertyType(() => baseZoneTypeEntity.BonusAmount);

I would like to have something like you pass the class instead of passing an instance, so something

Type t = GetPropertyType<ZoneTypeClass>(_ => _.BonusAmount);

Expressions are quite new to me and im trying to convert this for half an hour already and to no avail.

Can you guys help me convert this to a class based from an object based one?

Thank you.

Upvotes: 0

Views: 137

Answers (2)

Danny D
Danny D

Reputation: 875

you need to change the expression parameter to object try this.

      private static Type GetPropertyType<TClass>(Expression<Func<TClass, object>> propertyExpression)
    {
        var unaryExpression = propertyExpression.Body as UnaryExpression;

        if (unaryExpression == null) return propertyExpression.Body.Type;

        var type = unaryExpression.Operand.Type;

        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof (Nullable<>))
        {
            type = Nullable.GetUnderlyingType(type);
        }

        return type;
    }

UPDATED : the expression body needs to be casted to UnaryExpression the above should work Then you can use it as

 var type= GetPropertyType<CustomerEntity>(x => x.FirstName);

Or

    var type= GetPropertyType<ProductEntity>(_ => _.Price);

Upvotes: 0

Bas
Bas

Reputation: 27095

In your current approach you'd write:

Type t = GetPropertyType<ZoneTypeClass, int>(_ => _.BonusAmount)

Which is redundant since you'd either have to pass in an instance or specify the resulting type. You could rewrite the method to not care about the resulting type, but leave it as object. This is possible because you are inspecting the expression body, allowing the desired behavior posted in your question (using _ => _.Property).

static Type GetPropertyType<TObject>(Expression<Func<TObject, object>> propertyExpression)
{
    var expression = propertyExpression.Body;
    var unaryExpression = expression as UnaryExpression;
    if (unaryExpression != null)
    {
        expression = unaryExpression.Operand;
    }
    Type type = expression.Type;
    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
    {
        type = Nullable.GetUnderlyingType(type);
    }
    return type;
}

Why the weird UnaryExpression if statement? If your property type is not of type object, the expression will evaluate to _ => ((object)_.Property). The UnaryExpression is the type conversion part, which we are eliminating there.

Upvotes: 1

Related Questions