C# 从单个对象中选择作为表达式
如何将表达式应用于单个项?现在,我有一个表达式,可以用于支持Select扩展方法的列表或任何集合。我还想将该功能扩展到单个对象。下面是一个例子来阐明我的意思:C# 从单个对象中选择作为表达式,c#,.net,linq,C#,.net,Linq,如何将表达式应用于单个项?现在,我有一个表达式,可以用于支持Select扩展方法的列表或任何集合。我还想将该功能扩展到单个对象。下面是一个例子来阐明我的意思: private static readonly Expression<Func<Book, BookDto>> AsBookDto = x => new BookDto { Title = x.Title, Author = x.
private static readonly Expression<Func<Book, BookDto>> AsBookDto =
x => new BookDto
{
Title = x.Title,
Author = x.Author.Name,
Genre = x.Genre,
Description = x.Description,
Price = x.Price,
PublishDate = x.PublishDate
};
大多数LINQ扩展在
IEnumerable
或IQueryable
上工作,在您的情况下,您需要的只是一个普通的函数/委托,但如果您想保持与LINQ相同的语法,只需为此编写您自己的扩展方法:
public static TOutput SelectSingle<TInput, TOutput>(
this TInput obj,
Expression<Func<TInput, TOutput>> expression)
{
return expression.Compile()(obj);
}
省略了错误检查,但正如您所看到的,直接这样使用它并没有什么好处:
IQueryable<BookDto> books = db.Books.Include(b => b.Author)
.Where(x => x.AuthorId == authorId).Select(AsBookDto);
public BookDto SampleMethod(Book propertiesIncludedBook)
{
//this does not compile because Book does not have a Select method.
return propertiesIncludedBook.Select(AsBookDto);
}
public BookDto SampleMethod(Book propertiesIncludedBook)
{
return AsBookDto.Compile()(propertiesIncludedBook);
}
Edit使用单独的
Func
功能的可选拆分表达式定义可以工作,但会使表达式本身变得毫无用处。已删除。这是否意味着您实际从数据库中检索到了完整的书籍对象?通常,DTO类的使用方式是直接投影到它们,就像您在第一个示例中所做的那样。做你要求的是可能的,但可能不是你想要的,因为它的行为方式不同:例如,x.Author.Name
会突然导致NullReferenceException
如果x.Author==null
(即使在数据库中设置了作者,也可能发生这种情况)。您能解释一下何时以及如何使用SampleMethod
?是的,我之所以尝试这样做,是因为我使用FirstOrDefault从数据库中获取了一个项目(包括表达式中使用的所有对象),然后根据检索到的对象的状态,我将选择应用于该对象的表达式,以将其转换为Dto。假设检索到的对象具有Inviter和Invitee属性(POCO),现在根据状态,我将使用AsInviterTo或AsInviteToTo。另一种方法可能是使用AutoMapper。此时,您可以在代码中选择要应用的映射。您的替代方案将永远无法工作,表达式树将不再包含任何有用的信息,它只会保存“invoke variableAsBookDtoFunc
”,而不包含有关AsBookDtoFunc
的功能的信息。但是你的第一个建议看起来无法进一步改进。谢谢你的回答,我在你提供的第一个示例中发现了一个错误。它告诉我expression.Compile()有两个构造函数,一个是默认的空构造函数,另一个接受System.RunTime.CompilerServices.DebugInfoGenerator对象,其中没有一个对'TInput obj'有效。我可以通过更改expression.Compile()使第一个示例工作part to`Func fun=expression.Compile();返回乐趣(obj);我想Adriano的意思是expression.Compile()(obj)
。不过,您所计算出的结果将以完全相同的方式工作。@hvd非常正确,这样表达式本身就没有意义了。
public BookDto SampleMethod(Book propertiesIncludedBook)
{
return AsBookDto.Compile()(propertiesIncludedBook);
}