从对象构建表达式
Build expression from object
我从 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 class:
[Table("MyTable")]
public class MyRow
{
public int Id {get;set;}
public string Name {get;set;}
public int Qunatity {get;set;}
}
现在我需要创建从 ModelFromClient
到 Expression<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 扩展方法。
免责声明:我是项目的所有者Entity Framework Plus
这里有一个 fiddle 可以帮助您入门: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});
正如@Jonathan Magnan 所说(谢谢 Jonathan),他的回答为我指明了正确的方向:
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);
}
以防万一有人搜索相同的解决方案。
我从 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 class:
[Table("MyTable")]
public class MyRow
{
public int Id {get;set;}
public string Name {get;set;}
public int Qunatity {get;set;}
}
现在我需要创建从 ModelFromClient
到 Expression<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 扩展方法。
免责声明:我是项目的所有者Entity Framework Plus
这里有一个 fiddle 可以帮助您入门: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});
正如@Jonathan Magnan 所说(谢谢 Jonathan),他的回答为我指明了正确的方向:
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);
}
以防万一有人搜索相同的解决方案。