General view in ASP.Net Core 2.0 using lambda expressions

I am trying to write a general view in ASP.NET Core 2.0 that I can use with several Model

Model:

public class MyList<T> : List<T> where T : class
{
    public IEnumerable<Expression<Func<T, object>>> Fields { get; set; }

    internal MyList(List<T> list, Expression<Func<T, object[]>> fields)
    {
        var res = new List<Expression<Func<T, object>>>();
        var param = Expression.Parameter(typeof(T), "x");
        foreach (MemberExpression item in ((NewArrayExpression)fields.Body).Expressions)
        {
            Expression con = Expression.Property(param, item.Member.Name);
            res.Add(Expression.Lambda<Func<T, object>>(con, param));
        }
        this.Fields = res;
    }

}

Creator Model: MyList Class

    public static async Task<MyList<T>> CreateAsync<T>(IQueryable<T> qry, Expression<Func<T, Object[]>> Props) where T : class
    {
        return new MyList<T>(await qry.ToListAsync(), Props);
    }

in the controller

var model = await MyList.CreateAsync(qry, x => new[] { x.Name, x.Code});

View:

@model MyList<Color>

<table class="table table-bordered">
<tbody>
    @foreach (var item in Model)
    {
        <tr>
            @foreach (var field in Model.Fields)
                {
                    <td>
                        @Html.DisplayForMe(modelItem => item,field)
                    </td>
                }
        </tr>
    }
</tbody>
</table>

DisplayForMe Extension

public static IHtmlContent DisplayForMe<TModel, TResult,TValue>(this IHtmlHelper<TModel> html, Expression<Func<TModel, TResult>> expression, Expression<Func<TResult,TValue>> exp2) where TModel : class
    {
        var con = Expression.Property(expression.Body, ((MemberExpression)exp2.Body).Member.Name);

        var oo = Expression.Lambda<Func<TModel, TValue>>(con, expression.Parameters);

        return html.DisplayFor(oo);
    }

Everything works fine when the T.Name and T.Code Type properties are String. When I go through x.Id (long) proplems is started.

All I want is a way to pass the html.DisplayFor () properties, so I can use the same view to display multiple models (in case I pass the displayed property names from the controller)

I am not familiar with lambda expressions

I tried passing properties as string [], but I don't know how to write a lambda expression that takes a property name and returns the correct expression for

html.DisplayFor<TModel,TResult>(oo) 

Please, help!

0

All Articles