gpt4 book ai didi

c# - 为其中包含嵌套实体的实体生成动态选择表达式

转载 作者:行者123 更新时间:2023-12-05 05:24:46 25 4
gpt4 key购买 nike

我有一个类,它具有类型为另一个实体的属性。如下所示:

public class InspectionTopicDataAllViewModel 
{
public Guid Id { get; set; }
public Guid? UploadedFileId { get; set; }
public int InspectionId { get; set; }
public int InspectionTopicId { get; set; }

public SparseDataViewModel SparseData { get; set; }
}

public class SparseDataViewModel : SparseData
{
}

我需要编写一个能够只选择我想要的列的动态选择表达式。

我这样写:

private static Func<InspectionTopicDataAll, InspectionTopicDataAllViewModel> GetSparseInitExpression(List<string> columns)
{
Expression<Func<InspectionTopicDataAll, InspectionTopicDataAllViewModel>> commonSelector =
x => new InspectionTopicDataAllViewModel()
{
Id = x.Id,
InspectionId = x.InspectionId,
InspectionTopicId = x.InspectionTopicId,
UploadedFileId = x.UploadedFileId,
};


// input parameter "x"
var xParameter = Expression.Parameter(typeof(InspectionTopicDataAll), "x");

var xNew = Expression.New(typeof(InspectionTopicDataAllViewModel));

var sNew = Expression.New(typeof(SparseDataViewModel));

var bindings = new List<MemberBinding>();

// create initializers
foreach (var column in columns)
{
Expression srcBody = xParameter;

foreach (var member in column.Split('.'))
{
srcBody = Expression.PropertyOrField(srcBody, member);
}

var destMember = srcBody as MemberExpression;
// property "Field1"
var propInfo = destMember?.Member as PropertyInfo;

if (propInfo != null)
{

bindings.Add(Expression.Bind(propInfo, srcBody));
}
}

var sInit = Expression.MemberInit(sNew, bindings);

var zeroth = ((MemberInitExpression)commonSelector.Body);
var param = commonSelector.Parameters[0];
List<MemberBinding> newBindings = new List<MemberBinding>(zeroth.Bindings.OfType<MemberAssignment>());

var spNestedType = typeof (InspectionTopicDataAllViewModel).GetProperty(nameof(SparseData));

newBindings.Add(Expression.Bind(spNestedType, sInit));

var newInit = Expression.MemberInit(xNew, newBindings);

var childSelector = Expression.Lambda<Func<InspectionTopicDataAll, InspectionTopicDataAllViewModel>>(newInit, xParameter);

return childSelector.Compile();
}

并在我的主要查询中使用如下函数:

 var model = worksheetService.GetInspectionTopicData(inspectionTopicId, inspectionId, discrimintor, value).Select(GetSparseInitExpression(columns)).AsQueryable();

使用这个函数,我可以生成如下所需的表达式:

x => new InspectionTopicDataAllViewModel() 
{
Id = x.Id,
InspectionId = x.InspectionId,
InspectionTopicId = x.InspectionTopicId,
UploadedFileId = x.UploadedFileId,
SparseData = new SparseDataViewModel() {
MusteriNo = x.SparseData.MusteriNo,
MusteriAdi = x.SparseData.MusteriAdi,
CekNo = x.SparseData.CekNo,
Banka = x.SparseData.Banka,
CekTarihi = x.SparseData.CekTarihi,
Meblag = x.SparseData.Meblag,
PCN = x.SparseData.PCN,
Kesideci = x.SparseData.Kesideci}}}

但是当我运行表达式时抛出这个错误:

variable 'x' of type 'InternalControl.Domain.Entities.InspectionTopicDataAll' referenced from scope '', but it is not defined

我不知道如何解决这个错误...

更新:感谢@MBoros 的帮助,对于那些以后可能需要此类代码的人,使用上面的代码,即使代码有效并且可以从数据库中检索结果,但 select 语句不是按预期工作,所有列都从数据库中获取,所以为了解决这个问题,我使用了下面的代码:希望能帮助其他尝试做这种事情的人。

 private static Expression<Func<InspectionTopicDataAll, InspectionTopicDataAllViewModel>> GetCustomSelectExpression(List<string> columns)
{
Expression<Func<InspectionTopicDataAll, InspectionTopicDataAllViewModel>> commonSelector =
x => new InspectionTopicDataAllViewModel()
{
Id = x.Id,
InspectionId = x.InspectionId,
InspectionTopicId = x.InspectionTopicId,
UploadedFileId = x.UploadedFileId,
};


// input parameter "x"
var xParameter = commonSelector.Parameters[0];

var xNew = Expression.New(typeof(InspectionTopicDataAllViewModel));

var sNew = Expression.New(typeof(SparseDataViewModel));

var bindings = new List<MemberBinding>();

// create initializers
foreach (var column in columns)
{
Expression srcBody = xParameter;

foreach (var member in column.Split('.'))
{
srcBody = Expression.PropertyOrField(srcBody, member);
}

var destColName = column.Substring(column.LastIndexOf('.')+1);
// property "Field1"
var propInfo = typeof(SparseDataViewModel).GetProperty(destColName);


if (propInfo != null)
{
bindings.Add(Expression.Bind(propInfo, srcBody));
}
}

var sInit = Expression.MemberInit(sNew, bindings);

var zeroth = ((MemberInitExpression)commonSelector.Body);

List<MemberBinding> newBindings = new List<MemberBinding>(zeroth.Bindings.OfType<MemberAssignment>());

var spNestedType = typeof (InspectionTopicDataAllViewModel).GetProperty(nameof(SparseData));

newBindings.Add(Expression.Bind(spNestedType, sInit));

var newInit = Expression.MemberInit(xNew, newBindings);

var childSelector = Expression.Lambda<Func<InspectionTopicDataAll, InspectionTopicDataAllViewModel>>(newInit, xParameter);

return childSelector;
}

并使用它代替如下的 select 语句:

var model =
worksheetService.GetInspectionTopicData(inspectionTopicId, inspectionId, discrimintor, value)
.Select(GetCustomSelectExpression(columns));

最佳答案

您的 childSelector 不知道 commonSelectorx 参数。在表达式树中,参数是按实例识别的,而不仅仅是按名称识别的,因此两个 x 参数实际上是不同的(即使在调试 View 中它们看起来相同)。

最简单的解决办法可能是改变你的

// input parameter "x"
var xParameter = Expression.Parameter(typeof(InspectionTopicDataAll), "x");

var xParameter = commonSelector.Parameters[0]; 

这应该可以解决问题:)

关于c# - 为其中包含嵌套实体的实体生成动态选择表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33653376/

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