Construir la expresión del objeto

c# entity-framework-plus expression reflection

Pregunta

Recibo el siguiente objeto de la aplicación cliente Angular en ASP.NET Core:

public class ModelFromClient
{
  public string name {get;set;}      //Database field is Name
  public int qunatity {get;set;}     //Database field is Quantity
}

Y tengo una clase de tabla EF:

public class ModelFromClient
{
  public string name {get;set;}      //Database field is Name
  public int qunatity {get;set;}     //Database field is Quantity
}

Ahora necesito crear la expresión de ModelFromClient a Expression<Func<MyRow, MyRow>> y la necesito con genérico. Sin los genéricos la solución sería:

public class ModelFromClient
{
  public string name {get;set;}      //Database field is Name
  public int qunatity {get;set;}     //Database field is Quantity
}

Pero me gustaría algo así:

public class ModelFromClient
{
  public string name {get;set;}      //Database field is Name
  public int qunatity {get;set;}     //Database field is Quantity
}

Necesito una expresión para pasarlo al método de extensión de actualización de EntityFramework-Plus.

Respuesta aceptada

Descargo de responsabilidad : soy el propietario del proyecto Entity Framework Plus

Aquí hay un violín para comenzar: https://dotnetfiddle.net/JY0wzw

using System;
using System.Collections.Generic;
using System.Linq.Expressions;

public class Program
{
    public class MyRow
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Qunatity { get; set; }
    }

    public static void Main()
    {
        var type = typeof(MyRow);
        var constructorInfo = type.GetConstructor(new Type[0]);
        var newExpression = Expression.New(constructorInfo);

        var memberInits = new List<MemberAssignment>();
        foreach (var prop in type.GetProperties())
        {
            if (prop.Name == "Id")
            {
                memberInits.Add(Expression.Bind(prop, Expression.Constant(1)));
            }
            else if (prop.Name == "Name")
            {
                memberInits.Add(Expression.Bind(prop, Expression.Constant("Z_Name")));
            }
            else if (prop.Name == "Qunatity")
            {
                memberInits.Add(Expression.Bind(prop, Expression.Constant(2)));
            }
        }

        var expression = Expression.MemberInit(newExpression, memberInits);

        // FOR testing purpose
        var compiledExpression = Expression.Lambda<Func<MyRow>>(expression).Compile();
        var myRow = compiledExpression();

        Console.WriteLine(myRow.Id);
        Console.WriteLine(myRow.Name);
        Console.WriteLine(myRow.Qunatity);
    }
}

Descargo de responsabilidad : soy el propietario del proyecto Eval-Expression.NET

Esta biblioteca no es gratuita, pero le permite crear código dinámicamente en tiempo de ejecución. Una vez que se haya familiarizado, puede hacer prácticamente todo lo que quiera con más facilidad que con la solución anterior.

using System;
using System.Collections.Generic;
using System.Linq.Expressions;

public class Program
{
    public class MyRow
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Qunatity { get; set; }
    }

    public static void Main()
    {
        var type = typeof(MyRow);
        var constructorInfo = type.GetConstructor(new Type[0]);
        var newExpression = Expression.New(constructorInfo);

        var memberInits = new List<MemberAssignment>();
        foreach (var prop in type.GetProperties())
        {
            if (prop.Name == "Id")
            {
                memberInits.Add(Expression.Bind(prop, Expression.Constant(1)));
            }
            else if (prop.Name == "Name")
            {
                memberInits.Add(Expression.Bind(prop, Expression.Constant("Z_Name")));
            }
            else if (prop.Name == "Qunatity")
            {
                memberInits.Add(Expression.Bind(prop, Expression.Constant(2)));
            }
        }

        var expression = Expression.MemberInit(newExpression, memberInits);

        // FOR testing purpose
        var compiledExpression = Expression.Lambda<Func<MyRow>>(expression).Compile();
        var myRow = compiledExpression();

        Console.WriteLine(myRow.Id);
        Console.WriteLine(myRow.Name);
        Console.WriteLine(myRow.Qunatity);
    }
}

Respuesta popular

Como dijo @Jonathan Magnan (gracias Jonathan), su respuesta me indica la dirección correcta:

public static Expression<Func<T, T>> ToExpressionGeneric<T>(this object Model) where T : new()
{
    var type = typeof(T);
    var constructorinfo = type.GetConstructor(new Type[0]);
    var newExpression = Expression.New(constructorinfo);

    var memberInits = new List<MemberAssignment>();

    var modelProperties = Model.GetType().GetProperties();
    foreach (var prop in type.GetProperties())
    {
        var modelProperty = modelProperties.Where(t => t.Name == prop.Name.FirstLetterToLowerCase()).SingleOrDefault();
        if (modelProperty != null)
            memberInits.Add(Expression.Bind(prop, Expression.Constant(modelProperty.GetValue(Model, null))));
    }

    var expression = Expression.MemberInit(newExpression, memberInits);

    var p = Expression.Parameter(typeof(T), "p");

    return Expression.Lambda<Func<T, T>>(expression, p);
}

public static string FirstLetterToLowerCase(this string s)
{
    if (string.IsNullOrEmpty(s))
        throw new ArgumentException("There is no first letter");

    char[] a = s.ToCharArray();
    a[0] = char.ToLower(a[0]);
    return new string(a);
}

Por si acaso si alguien busca la misma solución.




Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué