C# 创建动态linq语句

C# 创建动态linq语句,c#,linq,C#,Linq,我的应用程序中有一个模型如下所示: 公共类PersonViewModel { 公共Guid Id{get;set;} 公共字符串DisplayName{get;set;} 公共字符串名{get;set;} 公共字符串LastName{get;set;} 公共字符串Upn{get;set;} // ... } 目前,我正在使用此扩展方法进行选择: public static IQueryable SelectBasic(此IQueryable personViewModels) { 返回pers

我的应用程序中有一个模型如下所示:

公共类PersonViewModel
{
公共Guid Id{get;set;}
公共字符串DisplayName{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串Upn{get;set;}
// ...
}
目前,我正在使用此扩展方法进行选择:

public static IQueryable SelectBasic(此IQueryable personViewModels)
{
返回personViewModels。选择(p=>new PersonViewModel
{
Id=p.Id,
DisplayName=p.DisplayName,
Upn=p.Upn
});
}
//这个用起来像
dbContext.People.AsQueryable().SelectBasic();
//这将与dbContext.People.AsQueryable()相同;
我想将select语句转换为动态语句,如下所示。但我不知道如何创建Linq表达式来实现这一点

公共静态IQueryable SelectProperties(此IQueryable personViewModels,
string propertyNames=“Id,DisplayName,Upn”)
{
var properties=propertyNames.Split(',');
返回personViewModels。选择(p=>new PersonViewModel
{
//仅选择属性数组中的属性
});
}
//像
dbContext.People.AsQueryable().SelectProperties(“Id,Upn”);
我找到了
System.Linq.Expressions
名称空间,但文档很难找到。我找不到任何关于它的样品。注意:我不想要匿名类型,因为这是dotnet core 3 web api将返回的内容


我正在尝试选择动态参数(用户指定)。我没有尝试使用动态过滤器。

使用原始选择

personViewModels.Select(p => 
    new PersonViewModel {
        Id = p.Id,
        DisplayName = p.DisplayName,
        Upn = p.Upn
    }
);
作为需要为所需
表达式构建的表达式树的指南,请选择
表达式

参考文献 请注意与以下代码关联的注释,以了解select表达式是如何动态构建的

public static IQueryable<PersonViewModel> SelectProperties(
    this IQueryable<PersonViewModel> personViewModels,
    string propertyNames = "Id,DisplayName,Upn") {

    var properties = propertyNames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
    var type = typeof(PersonViewModel);
    // p =>
    var parameter = Expression.Parameter(type, "p");
    // create bindings for initialization
    var bindings = properties
        .Select(s => {
            // property
            var property = type.GetProperty(s);
            // original value 
            var propertyExpression = Expression.Property(parameter, property);
            // set value "Property = p.Property"
            return Expression.Bind(property, propertyExpression);
        }
    );
    // new PersonViewModel()
    var newViewModel = Expression.New(type);
    // new PersonViewModel { Property1 = p.Property1, ... }
    var body = Expression.MemberInit(newViewModel, bindings);
    // p => new PersonViewModel { Property1 = p.Property1, ... }
    var selector = Expression.Lambda<Func<PersonViewModel, PersonViewModel>>(body, parameter);

    return personViewModels.Select(selector);
}
公共静态IQueryable SelectProperties(
这个IQueryable personViewModels,
string propertyNames=“Id,DisplayName,Upn”){
var properties=propertyNames.Split(新字符[]{',},StringSplitOptions.RemoveEmptyEntries);
变量类型=类型(PersonViewModel);
//p=>
var参数=表达式参数(类型为“p”);
//为初始化创建绑定
var绑定=属性
。选择(s=>{
//财产
var property=type.GetProperty;
//原值
var propertyExpression=Expression.Property(参数,属性);
//设置值“Property=p.Property”
返回表达式Bind(property,propertyExpression);
}
);
//新PersonViewModel()
var newViewModel=Expression.New(类型);
//新PersonViewModel{Property1=p.Property1,…}
var body=Expression.MemberInit(newViewModel,绑定);
//p=>new PersonViewModel{Property1=p.Property1,…}
变量选择器=表达式.Lambda(主体,参数);
返回personViewModels。选择(选择器);
}

引用我甚至不理解你的代码。@MarcoSalerno我已经试着使示例代码更好。我的主要问题是为什么?我看不出您的扩展方法比普通的
有任何优势。选择
?我想字符串在运行时可能会更改?这就是你在这里想要实现的吗?@Liam这正是我想要实现的!您在示例代码中的注释非常有用。这就是我问题的解决办法!下面是代码的通用版本