Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

172
Views
Expression tree to create lambda for generating a c# dictionary

I have a stream of thousands of data which I need to transform and add to a list. The transformation happens through the reflection similar to following

_myObservable.Subscribe(d => {
    PropertyInfo[] props = d.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
    var propValDict = props.ToDictionary(prop => prop.Name, prop => prop.GetValue(d, null));
    myList.Add(propValDict);
});

// Datatype of d is determined during runtime and there are only 8 possibilities of the type

But this approach is slowing down the performance and I expect the use of reflection might be the reason. I am thinking of improving the performance by some other means.

Suggestions seem to point at use of Expression trees, create compiled lambda (Func<object,Dictionary<string, object>>) and store it in a lookup dictionary before hand.

//Foreach possibleType in PossibleTypes, Do below

PropertyInfo[] props = possibleType.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);

var rootParam = Expression.Parameter(typeof(object), "d");
var param = Expression.Parameter(typeof(PropertyInfo), "prop");
var propertyFirst = Expression.Property(param, "Name");

var param2 = Expression.Parameter(typeof(PropertyInfo), "prop");
var callMethod = Expression.Call(param2, typeof(PropertyInfo).GetMethod(nameof(PropertyInfo.GetValue), new Type[] { typeof(object) }), rootParam);

var pro = Expression.Parameter(typeof(Array), "props");

var toDict = Expression.Invoke(pro, propertyFirst, callMethod);
var lambda = Expression.Lambda<Func<object, Dictionary<string, object>>>(toDict, rootParam);
var compiled = lambda.Compile();

I am having trouble to invoke ToDictionary of Enumerable class There is something which I am missing with this approach or Will this really improve performance.

Please help...

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

When thinking with expressions, you always need to figure out what the equivalent C# code would look like. In this case, the equivalent C# code wouldn't be looping over a collection of PropertyInfo, instead it would probably look like:

public static Func<object, Dictionary<string, object>> CreateConvertToPropertyDict<T>()
{
    return input =>
    {
        var d = (T)input;
        return new Dictionary<string, object>())
        {
            { "Foo", d.Foo },
            { "Bar", d.Bar },
        };
    };
}
myList.Add(propValDict);

Move sidewards in the land of expressions, and you end up with something like:

public static Func<object, Dictionary<string, object>> CreatePropertyDict(Type type)
{
    // Consider caching these in a static field, since they're constant
    var dictType = typeof(Dictionary<string, object>);
    var dictCtor = dictType.GetConstructor(new[] { typeof(int) });
    var dictAddMethod = dictType.GetMethod("Add");

    var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
    
    var blockExpressions = new List<Expression>();
    
    // 'object input' is our input parameter
    var inputParameter = Expression.Parameter(typeof(object), "input");
    // MyType d;
    var dVariable = Expression.Variable(type, "d");
    // d = (MyType)inputObject;
    blockExpressions.Add(Expression.Assign(dVariable, Expression.Convert(inputParameter, type)));
    // Dictionary<string, object> dict;
    var dictVariable = Expression.Variable(dictType, "dict");
    // dict = new Dictionary<string, object>(3) (or however many properties there are)
    blockExpressions.Add(Expression.Assign(dictVariable, Expression.New(dictCtor, Expression.Constant(properties.Length))));
    
    foreach (var property in properties)
    {
        var propertyAccess = Expression.Property(dVariable, property);
        // dict.Add("Foo", (object)d.Foo)
        blockExpressions.Add(Expression.Call(
            dictVariable,
            dictAddMethod,
            Expression.Constant(property.Name),
            Expression.Convert(propertyAccess, typeof(object))));
    };
    
    // The final statement in a block is the return value
    blockExpressions.Add(dictVariable);
    
    var block = Expression.Block(new[] { dVariable, dictVariable }, blockExpressions);
    return Expression.Lambda<Func<object, Dictionary<string, object>>>(block, inputParameter).Compile();
}

With the simple test case:

public static void Main()
{
    var test = new Test() { Foo = "woop", Bar = 3 };
    var expr = CreatePropertyDict(typeof(Test));
    expr(test).Dump();
}

See it on dotnetfiddle.

There are several more advanced usages of Expression here, and I'm not going to go into the detail of each one. Look at the docs, and have a play around with the sorts of expressions that the C# compiler generates for different bits of C# code.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!