Currently the thing you are asking for is not easy to implement, because to handle projections NHibernate uses ClientSideResultOperator additional to HQL (see QueryModelVisitor
.VisitSelectClause
methd)
For example for following query
var q = from c in this.Session.Query<Customer>()
select new Card
{
FirstName = c.FirstName,
LastName = c.LastName,
FullName = c.FirstName + " " + c.LastName
};
NHibernate translates projection to array based projection
var q = from c in this.Session.Query<Customer>()
select new object[]
{
c.FirstName,
c.LastName,
c.FirstName + " " + c.LastName
};
And adds folowing transformation result
Expression<Func<object[], Card>> projectionExpression = array => new Card
{
FirstName = (string)array[0],
LastName = (string)array[1],
FullName = (string)array[2]
};
But it may work only for following simplier case:
var q = from c in this.Session.Query<Customer>()
select c.GetCart();
Alternative solution
I can suggest pre-process query expression to inline GetCart
method. You can do it manually, or use DelegateDecompiler. DelegateDecompiler has extension method .Decompile(this IQueryable<T> self)
which looks expression tree for methods and properties marked with [Decomile]
or [Computed]
attributes and inlines these methods and properties.
So you can do following
var q = (from c in this.Session.Query<Customer>()
select new { Id = c.Id, InfoCard = c.GetCard() }).Decompile();
[Decompile]
public static string GetCard(this Customer @this)
{
return new Card
{
FirstName = @this.FirstName,
LastName = @this.LastName,
FullName = @this.FirstName + " " + @this.LastName
};
}
The query will be transformed to
var q = from c in this.Session.Query<Customer>()
select new
{
Id = c.Id,
InfoCard = new Card
{
FirstName = c.FirstName,
LastName = c.LastName,
FullName = c.FirstName + " " + c.LastName
})
};