【问题标题】:Build expression from object从对象构建表达式
【发布时间】:2018-05-08 04:42:13
【问题描述】:

我从 ASP.NET Core 中的 Angular 客户端应用程序收到以下对象:

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

我有一个 EF Table 类:

[Table("MyTable")]
public class MyRow
{
  public int Id {get;set;}  
  public string Name {get;set;}
  public int Qunatity {get;set;}
}

现在我需要创建从ModelFromClientExpression<Func<MyRow, MyRow>> 的表达式,并且我需要它的泛型。 没有泛型的解决方案是:

public Expression<Func<MyRow, MyRow>> ToExpression(ModelFromClient Model)
{
    Expression<Func<MyRow, MyRow>> result = (t) => new MyRow()
    {
        Name = Model.name, 
        Quantity = Model.qunatity
    };
    return result;
}

但我想要这样的东西:

public Expression<Func<T, T>> ToExpression<T>(object Model) where T: new()
{
    Expression<Func<T, T>> result = (t) => new T();
    foreach(var prop in Model.GetType().GetProperties()) 
    {
       //compile error Fields does not exists.
       result.Body.Fields.Add(prop.Name.Capitalize(), prop.GetValue(Model, null));  //capitalize returns Name from input name
    }
    return result;
}

我需要表达式将其传递给 EntityFramework-Plus 的 Update 扩展方法。

【问题讨论】:

  • 请在答案中发布您的解决方案,而不是作为对问题的编辑以了解更多信息,请参阅tour
  • 如果您觉得现有答案不够充分,需要发布您自己的答案,请发布解决方案作为答案,而不是作为对题。问题是您在哪里提出问题,而不是您在哪里发布解决方案。

标签: c# reflection expression entity-framework-plus


【解决方案1】:

免责声明:我是项目的所有者Entity Framework Plus

这里有一个帮助你入门的方法: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);
    }
}

免责声明:我是项目的所有者Eval-Expression.NET

此库不是免费的,但允许您在运行时动态创建代码。熟悉后,您可以比以前的解决方案更轻松地做任何您想做的事情。

// Register your type
EvalManager.DefaultContext.RegisterType(typeof(MyRow));

// Register extension methods once from Z.EntityFramework.Plus
EvalManager.DefaultContext.RegisterExtensionMethod(typeof(BatchUpdate));

Eval.Execute("query.Update(x => new MyRow() { Id = 1, Name = 'Z_Name', Qunatity = 2});", new {query});

【讨论】:

    【解决方案2】:

    正如@Jonathan Magnan 所说(谢谢乔纳森),他的回答为我指明了正确的方向:

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

    以防万一有人会搜索相同的解决方案。

    【讨论】:

      猜你喜欢
      • 2018-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-25
      • 2014-06-06
      • 1970-01-01
      相关资源
      最近更新 更多