0

I have a generic func that takes a string of fields and selects them from an object using linq. However the output is not type of object but a subset of. So to convert this new List<subsetOfOriginal> to a DataTable, I cannot use list.GetType() because it will get me Original.

I have converted

Func<T, T> CreateSelectStatement<T>(string fields)

to

Func<T, S> CreateSelectStatement<T, S>(string fields)

because I don't want TResult to be of type T. Not sure if this is the correct way. This is the code I have at the moment and how it is invoked.

Func<T, S> CreateSelectStatement<T, S>(string fields)
    {
        var xParameter = Expression.Parameter(typeof(T), "o");
        var xNew = Expression.New(typeof(T));
        var bindings = fields.Split(',').Select(o => o.Trim())
            .Select(o => {
        var mi = typeof(T).GetProperty(o);
        var xOriginal = Expression.Property(xParameter, mi);
        return Expression.Bind(mi, xOriginal);
            }
        );

        var xInit = Expression.MemberInit(xNew, bindings);
        var lambda = Expression.Lambda<Func<T, S>>(xInit, xParameter);
        return lambda.Compile();
    }

and then to invoke it I'm using

CreateSelectStatement<SP_ProjectAnalysis_NP, dynamic>(columns)

Expected outcome should be the fields that are loading correctly but the type of the object is as if I used p => new { }. Currently I am getting object as the return type and trying to perform the following gets me 0 properties:

private static DataTable ToDataTable<T>(IList<T> list, string tableName = "table")
        {
            PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
NetMage
  • 26,163
  • 3
  • 34
  • 55
  • kindly fix the block codes for me (the pointed brackets do not want to show). – Justin Farrugia Jul 11 '19 at 17:14
  • Perhaps get a copy of LINQPad and use the `Dump` statement to verify the `lambda` is what you expect? The code seems okay to me - but your usage perhaps not. If your calling `Expression.New(typeof(T))` then by definition the result will be of type `T` and not type `S`. I believe `dynamic` is treated like `object` for Reflection, so you really need to have `Func`. Also, what type is being passed into the returned `Func`? If it is already a `T` I don't see the point... – NetMage Jul 11 '19 at 18:24
  • @NetMage Ok so that draws me closer to the solution or at least to a better explanation. I actually want to have `Expression.New(typeof(S))` and not `T`, you're right. So the user is selecting columns from a table arbitrarily and I want `S` to dynamically become an object of the new class containing the new columns as properties. Because after that I am passing list of `S` to an excel creator. I don't want `T` because `T` will give me a lot of columns with null values then (the un-selected). – Justin Farrugia Jul 15 '19 at 07:59
  • Perhaps consider [LINQKit](https://github.com/scottksmith95/LINQKit) which includes runtime anonymous object creation? Unfortunately, creating anonymous objects at runtime is a lot of work (I think I might have posted the code here) but perhaps you could consider using something like `DataTable`? – NetMage Jul 15 '19 at 13:37
  • Here is my [simplified anonymous object creator](https://stackoverflow.com/a/56408259/2557128) code. – NetMage Jul 15 '19 at 17:14

0 Answers0