如果我有这样的课程
`
class Person
{
public string First;
public string Last;
public bool IsMarried;
public int Age;
}`
那么如何编写LINQ表达式,我可以在其中选择Person的属性。我想做这样的事情(用户可以输入1..n属性)
SelectData<Person>(x=>x.First, x.Last,x.Age);
我的SelectData函数的输入表达式是什么?
SelectData(Expression<Func<TEntity, List<string>>> selector); ?
修改 在我的SelectData函数中,我想提取属性名,然后动态生成我的SQL查询的SELECT子句。
解 好的,我所做的就是将我的SelectData作为
public IEnumerable<TEntity> SelectData(Expression<Func<TEntity, object>> expression)
{
NewExpression body = (NewExpression)expression.Body;
List<string> columns = new List<string>();
foreach(var arg in body.Arguments)
{
var exp = (MemberExpression)arg;
columns.Add(exp.Member.Name);
}
//build query
使用它我称之为
ccc<Person>().SelectData(x => new { x.First, x.Last, x.Age });
希望它会帮助那些正在寻找的人:)
谢谢, IY
答案 0 :(得分:0)
您可以使用Reflection和Extension Method
获得类似的结果型号:
namespace ConsoleApplication2
{
class Person
{
public string First { get; set; }
public string Last { get; set; }
public bool IsMarried { get; set; }
public int Age { get; set; }
}
}
服务:
using System.Collections.Generic;
using System.Linq;
namespace Test
{
public static class Service
{
public static IQueryable<IQueryable<KeyValuePair<string, object>>> SelectData<T>(this IQueryable<T> queryable, string[] properties)
{
var queryResult = new List<IQueryable<KeyValuePair<string, object>>>();
foreach (T entity in queryable)
{
var entityProperties = new List<KeyValuePair<string, object>>();
foreach (string property in properties)
{
var value = typeof(T).GetProperty(property).GetValue(entity);
var entityProperty = new KeyValuePair<string, object>(property, value);
entityProperties.Add(entityProperty);
}
queryResult.Add(entityProperties.AsQueryable());
}
return queryResult.AsQueryable();
}
}
}
用法:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Test
{
class Program
{
static void Main(string[] args)
{
var list = new List<Person>()
{
new Person()
{
Age = 18,
First = "test1",
IsMarried = false,
Last = "test2"
},
new Person()
{
Age = 40,
First = "test3",
IsMarried = true,
Last = "test4"
}
};
var queryableList = list.AsQueryable();
string[] properties = { "Age", "Last" };
var result = queryableList.SelectData(properties);
foreach (var element in result)
{
foreach (var property in element)
{
Console.WriteLine($"{property.Key}: {property.Value}");
}
}
Console.ReadKey();
}
}
}
结果:
Age: 18
Last: test2
Age: 40
Last: test4
答案 1 :(得分:0)
我认为使用委托而不是反射会更好。除了委托更快的事实之外,如果您尝试获取不存在的属性值,编译器会抱怨。使用反射,在运行时之前不会发现错误。
幸运的是,已经有类似的东西了。它被实现为IEnumerable的扩展函数,它被称为Select(具有讽刺意味)我想你想要这样的东西:
我有一系列人员,我希望你创建一个Linq 每个Person返回一个包含该对象的新对象的语句 属性第一和最后。
或者:
我有一系列Persns,我希望你创建一个Linq语句 每个Person返回一个包含Age,IsMarried的新对象, 是否是一个成年人并使其变得困难:一个财产叫做 名称是First和Last的组合
函数SelectData将是这样的:
IEnumerable<TResult> SelectData<TSource, TResult>(this IEnumerable<TSource> source,
Func<TSource, TResult> selector)
{
return source.Select(selector);
}
用法:
问题1:每个人返回一个包含该对象的新对象 属性第一和最后。
var result = Persons.SelectData(person => new
{
First = person.First,
Last = person.Last,
});
问题2:每个人返回一个包含Age,IsMarried的新对象,他是否是一个成年人和一个名为Name的属性,它是一个组合 第一个和最后一个
var result = Persons.SelectData(person => new
{
Age = person.Name,
IsMarried = person.IsMarried,
IsAdult = person.Age > 21,
Name = new
{
First = person.First,
Last = person.Last,
},
});
让我们面对现实吧,你的SelectData只不过是Enumerable.Select
你当然可以创建一个函数,你可以让调用者提供他想要的属性列表,但是(1)这将限制他设计最终结果的可能性,以及(2)它会更多地输入他打电话给这个职能部门。
而不是:
.Select(p => new
{
P1 = p.Property1,
P2 = p.Property2,
}
他必须键入类似
的内容.SelectData(new List<Func<TSource, TResult>()
{
p => p.Property1, // first element of the property list
p -> p.Property2, // second element of the property list
}
您将无法命名返回的属性,您将无法将多个属性合并为一个:
.Select(p => p.First + p.Last)
你会从中获得什么?
非常沮丧的要求!