gpt4 book ai didi

c# - 有没有办法在 lambda 表达式树中使用 `dynamic`?

转载 作者:可可西里 更新时间:2023-11-01 07:48:11 25 4
gpt4 key购买 nike

首先,规范。我们使用 MVC5、.NET 4.5.1 和 Entity Framework 6.1。

在我们的 MVC5 业务应用程序中,我们有很多重复的 CRUD 代码。我的工作是“自动化”其中的大部分,这意味着将其提取到基类并使其可重用。现在,我有 Controller 、 View 模型和 EF6 实体模型的基类。

所有 EF6 实体继承的我的抽象基类:

public abstract class BaseEntity<TSubclass>
where TSubclass : BaseEntity<TSubclass>
{
public abstract Expression<Func<TSubclass, object>> UpdateCriterion();
}

UpdateCriterion方法用于AddOrUpdate数据库上下文的方法。我有一个子类的通用参数,因为 UpdateCriterion需要返回使用精确子类类型的 lambda 表达式,而不是接口(interface)或基类。实现此抽象基类的极其简化的子类如下所示:

public class Worker : BaseEntity<Worker>
{
public int ID { get; set; }
public int Name { get; set; }

public override Expression<Func<Worker, object>> UpdateCriterion()
{
return worker => worker.ID;
}
}

在那之后,在SaveOrUpdate我的基本 Controller 的 Action ,我会有这样的代码:

public ActionResult Save(TViewModel viewModel)
{
if (ModelState.IsValid)
{
var entityModel = viewModel.ConstructEntityModel();
db.Set<TEntityModel>().AddOrUpdate<TEntityModel>(entityModel.UpdateCriterion(), entityModel);
db.SaveChanges();
}
}

多亏了这一点,基本 Controller 的子类不需要实现 Save方法自己,就像他们以前做的那样。现在,所有这些都有效,而且尽管语法很时髦(我是说 class BaseEntity<TSubclass> where TSubclass : BaseEntity<TSubclass> ,认真的?),但它实际上工作得很好。

我的问题来了。对于大多数实体字段 ID是关键,但对于某些人来说不是,所以我不能用父类(super class)实现正确概括。所以现在,每个实体子类都实现它自己的 UpdateCriterion .但是,因为对于大多数(90% 以上)实体 e => e.ID是正确的实现,我有很多重复。所以我想将实体基类重写成这样:

public abstract class BaseEntity<TSubclass> 
where TSubclass : BaseEntity<TSubclass>
{
public virtual Expression<Func<TSubclass, object>> UpdateCriterion()
{
return entity => ((dynamic)entity).ID;
}
}

目的是提供使用 ID 作为键的默认实现,并允许子类在使用不同键时覆盖它。我不能使用带有 ID 字段的接口(interface)或基类,因为并非所有实体都有它。我以为我会使用 dynamic拉出ID字段,但出现以下错误:Error: An expression tree may not contain a dynamic operation .

那么,关于如何做到这一点有什么想法吗?反射会在基地工作吗 UpdateCriterion

最佳答案

不,您不能在 Linq to Entities 查询中使用动态。但您可以在运行时构建 Lambda 表达式。

public virtual Expression<Func<TSubclass, object>> UpdateCriterion()
{
var param = Expression.Parameter(typeof(TSubclass));
var body = Expression.Convert(Expression.Property(param, "ID"), typeof(object));

return Expression.Lambda<Func<TSubclass, object>>(body, param);
}

如果 TSubclass 类型没有 ID 属性 Expression.Property(param, "ID") 将抛出异常。

此外,您可以使用实体模型中的 MetadataWorkspace 来获取 TSubclass 的主键列。

关于c# - 有没有办法在 lambda 表达式树中使用 `dynamic`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24575500/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com