3

I am wanting to extend my IQueryable to take a List of fieldnames and only return those columns into a dynamic collection. Essentially I want to implement the "Select" with passed in field/column names. The method would look something like this:

private IQueryable<TEnity> SetSelect(IQueryable<TEntity> query, List<string> fieldnames)
{
  //Build up the Expression  here
  query = query.Select(expressionHere);
  return query;
}

So if I were querying against an object like:

public Class Dog
{
  int Id{get;set;}
  string Name{get;set;}
  string Color{get;set;}
  DateTime Birthdate{get;set;}
}

But I only wanted to get the Name and Birthdate I could extend the IQueryable by calling SetSelect(query, new List<string>{"Name", "Birthdate"});

And would be returned:

[{"Fido", 01-01-2017}, {"Spot", 05-04-1972}]

Has anybody done something similar, and can help me with building that Expression?

Thanks for any clarification.

NOTE: This is a .Net Core application

KickinMhl
  • 1,218
  • 3
  • 14
  • 32
  • this looks to already be answered [here](http://stackoverflow.com/questions/606104/how-to-create-linq-expression-tree-to-select-an-anonymous-type) – danatcofo Mar 15 '17 at 21:41
  • I forgot to add one key point. This is a .Net Core app. the referenced answer above uses some classes not available, that I am aware of. – KickinMhl Mar 16 '17 at 17:46
  • the last answer [shortcut](http://stackoverflow.com/a/28140345/740108) on the same question might be an easier path to a working solution. – danatcofo Mar 16 '17 at 21:06

1 Answers1

1

You Can generate dynamic select by call DynamicSelectGenerator in select from an entity.

public static Func<T, T> DynamicSelectGenerator<T>( string fields )
          {
            // get Properties of the T
            var fields = typeof(T).GetProperties().Select(propertyInfo => propertyInfo.Name).ToArray();

            // input parameter "o"
            var xParameter = Expression.Parameter(typeof(T), "o");

            // new statement "new Data()"
            var xNew = Expression.New(typeof(T));

            // create initializers
            var bindings = fields.Split( ',' ).Select(o => o.Trim())
                .Select(o =>
                {

                    // property "Field1"
                    var mi = typeof(T).GetProperty(o);

                    // original value "o.Field1"
                    var xOriginal = Expression.Property(xParameter, mi);

                    // set value "Field1 = o.Field1"
                    return Expression.Bind(mi, xOriginal);
                }
            );

            // initialization "new Data { Field1 = o.Field1, Field2 = o.Field2 }"
            var xInit = Expression.MemberInit(xNew, bindings);

            // expression "o => new Data { Field1 = o.Field1, Field2 = o.Field2 }"
            var lambda = Expression.Lambda<Func<T, T>>(xInit, xParameter);

            // compile to Func<Data, Data>
            return lambda.Compile();
        }

And for example use by this code:

var result = dbContextInstancs.EntityClass.Select(DynamicSelectGenerator<EntityClass>("Name", "Birthdate"));
Ali
  • 3,373
  • 5
  • 42
  • 54
  • 2
    You overrode the method's parameter "fields" with the full list of fields from the T parameter. So how can you build a limited list? – GregJF Oct 08 '17 at 23:37
  • @GregJF what do mean by _limited list_ ? in my answer example you could see the `fields` parameter is `("Name", "Birthdate")` ...you could send more/less fields to function – Ali Oct 09 '17 at 07:46