0

Given a Type T and a list of strings that are propertynames in T like {"prop1", "prop2"}

I would like to generate an expression like below that is a dynamic object:

Expression<Func<T, object>> in the format:  x => new {x.prop1, x.prop2}

I am able to create a single property accessor, but cant figure out the dynamic type for the expression.

    private Func<T, int> BuildChildSelectorLambda(string idPropertyName) {

        ParameterExpression argParam = Expression.Parameter(typeof(T), "x");
        Expression selector = Expression.Property(argParam, typeof(T).GetProperty(idPropertyName));
    
        return  Expression.Lambda<Func<T,int>>(selector, argParam).Compile();
        //TODO: CACHE EXPRESSIONS
    }
DerpDerp
  • 307
  • 1
  • 11
  • https://stackoverflow.com/questions/4024754/creating-an-anonymous-type-dynamically – Renat Aug 24 '23 at 17:43
  • @Renat I understand how to create the dynamic object, I am not sure how to create that statement using an Expression tree so that it is returnedas an Expression> – DerpDerp Aug 24 '23 at 18:06
  • Do you want to create a new kind of anonymous object (which is a lot of overhead) or could you use another type, like `Dictionary`? I am not sure how a dynamically created anonymous class with strong typing will help you since the compiler doesn't know about the property types, unless you are using the result in another Reflection context (e.g. ASP.Net table)? – NetMage Aug 24 '23 at 20:23

1 Answers1

0

In order to create an expression like that you need to have an actual class to create an instance of. When your code says new{x.prop1, x.prop2}, it's actually declaring an anonymous class that gets compiled with your code. If you don't have a specific class in mind, you may have to create one with something like System.Reflection.Emit or Roslyn. Then create an initializer expression targeting that class.

Or, depending on what you're trying to do, you may be able to get away with using a predefined generic class. For example, if you're merely trying to create an expression to pass to a GroupBy LINQ method, the names of the properties in the object you create don't really matter. So you could create some types like this:

class TargetTuple<T>{
    public T Prop1 {get; init;}
}
class TargetTuple<T1, T2>
{
    public T1 Prop1 { get; init; }
    public T2 Prop2 { get; init; }
}

And then build an expression tree which looks more like this:

(Expression<Func<Source, object>>)(x => new TargetTuple<string> { Prop1 = x.prop1 })
StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315