dimanche 6 décembre 2015

LINQ using PropertyInfo and nested property

I'm looking to create a Linq Where, based on a nested property.

Let's say this is my project:

public class Car {
    public Engine Engine { get; set; }
}


public class Engine {
    public int HorsePower { get; set; }
}


var myCar = new Car() {
    Engine = new Engine() {
        HorsePower = 400
    }
};

I use this code found somewhere, which allow to create Expression,

private Expression<Func<TItem, bool>> PropertyEquals<TItem, TValue>( PropertyInfo property, TValue value ) {
        var param = Expression.Parameter( typeof( TItem ) );
        var memberExp = Expression.Property( param, property );

        BinaryExpression body;

        //If nullable, Expression.Equal won't work even if the value is not null. So we convert to non nullable (the compared expression)
        Type typeIfNullable = Nullable.GetUnderlyingType( memberExp.Type );
        if ( typeIfNullable != null ) {
            var convertedExp = Expression.Convert( memberExp, Expression.Constant( value ).Type );
            body = Expression.Equal( convertedExp, Expression.Constant( value ) );
        } else {
            body = Expression.Equal( memberExp, Expression.Constant( value ) );
        }

        return Expression.Lambda<Func<TItem, bool>>( body, param );
    }

Now, I had like to have an equivalent, calling my method PropertyEquals

var engine = myCar.Select( c => c.Engine.HorsePower == 400 );

Something like

var property = GetPropertyForDotSequence( typeof( Car ), "Engine.HorsePower" );
.Select( PropertyEquals<TEntity, int>( property , 400 ) );

I found a method which allow to find property based on a dotted format (GetPropertyForDotSequence), which work properly, but return HorsePower property info, and not Engine.HorsePower, so I get an error saying Car doesnot have an int32 property called HorsePower.

private PropertyInfo GetPropertyForDotSequence ( Type baseType, string propertyName ) {
        var parts = propertyName.Split( '.' );

        return ( parts.Length > 1 )
            ? GetPropertyForDotSequence( baseType.GetProperty( parts[ 0 ] ).PropertyType, parts.Skip( 1 ).Aggregate( ( a, i ) => a + "." + i ) )
            : baseType.GetProperty( propertyName );
    }





Aucun commentaire:

Enregistrer un commentaire