Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

174
Vistas
Árbol de expresiones para crear lambda para generar el diccionario ac #

Tengo un flujo de miles de datos que necesito transformar y agregar a una lista. La transformación ocurre a través de la reflexión similar a la siguiente

 _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

Pero este enfoque está ralentizando el rendimiento y espero que el uso de la reflexión sea la razón. Estoy pensando en mejorar el rendimiento por otros medios.

Las sugerencias parecen apuntar al uso de árboles de expresión, crear lambda compilada (Func<object,Dictionary<string, object>>) y almacenarla en un diccionario de búsqueda de antemano.

 //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();

Tengo problemas para invocar ToDictionary de la clase Enumerable Hay algo que me falta con este enfoque o ¿Esto realmente mejorará el rendimiento?

Por favor ayuda...

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Al pensar con expresiones, siempre debe averiguar cómo se vería el código C# equivalente. En este caso, el código C# equivalente no estaría recorriendo una colección de PropertyInfo , sino que probablemente se vería así:

 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);

Muévase hacia los lados en la tierra de las expresiones, y terminará con algo como:

 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(); }

Con el caso de prueba simple:

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

Véalo en dotnetfiddle .

Hay varios usos más avanzados de Expression aquí, y no voy a entrar en los detalles de cada uno. Mire los documentos y juegue con los tipos de expresiones que genera el compilador de C# para diferentes bits de código de C#.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda