C# 使用方法在LINQ中投影嵌套DTO

C# 使用方法在LINQ中投影嵌套DTO,c#,nhibernate,linq-to-nhibernate,C#,Nhibernate,Linq To Nhibernate,假设我们有以下实体: public class Customer { public virtual int Id { get; set; } public virtual string FirstName { get; set; } public virtual string LastName { get; set; } } 此外,还有以下扩展方法: public static string GetCard(this Customer @this) {

假设我们有以下实体:

public class Customer
{
    public virtual int Id { get; set; }

    public virtual string FirstName { get; set; }

    public virtual string LastName { get; set; }
}
此外,还有以下扩展方法:

public static string GetCard(this Customer @this)
   {
         throw new InvalidOperationException("Use only in IQueryable");
   }
现在,我要执行以下查询:

var q = from c in this.Session.Query<Customer>()
        select new { Id = c.Id, InfoCard = c.GetCard() };
var q=this.Session.Query()中的c
选择新{Id=c.Id,InfoCard=c.GetCard()};
我认为创建和注册以下hql生成器就足够了:

class GetCardGenerator : BaseHqlGeneratorForMethod
{
    public GetCardGenerator()
    {
        SupportedMethods = new[]
        {
            ReflectionHelper.GetMethodDefinition(() => CustomerExtensions.GetCard(null))
        };
    }

    public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
    {
        Expression<Func<Customer, Card>> definition = c => new Card
            {
                FirstName = c.FirstName,
                LastName = c.LastName,
                FullName = c.FirstName + " " + c.LastName
            };

        return visitor.Visit(definition);
    }
}
类GetCardGenerator:basehqlGeneratorFormMethod
{
公共GetCardGenerator()
{
SupportedMethods=new[]
{
ReflectionHelper.GetMethodDefinition(()=>CustomerExtensions.GetCard(空))
};
}
公共重写HqlTreeNode BuildHql(MethodInfo方法、表达式targetObject、只读集合参数、HqlTreeBuilder treeBuilder、IHqlExpressionVisitor)
{
表达式定义=c=>新卡
{
FirstName=c.FirstName,
LastName=c.LastName,
全名=c.FirstName+“”+c.LastName
};
回访者。访问(定义);
}
}
不幸的是,异常NotSupportedException与消息MemberInit一起引发。在调查期间,我在Linq\Visitors\SelectClauseHqlNominator.cs中发现HQL不支持New和MemberInit表达式的评论

我的问题是:是否有可能创建将在LINQ查询的select子句中使用并用于创建和填充DTO对象的方法

更新:我不想让IQueryable从IQueryable变为IQueryable,但我正在寻找一种解决方案,允许我在任何地方从客户那里提取卡片,例如,我有一个订单实体引用客户,我想调用如下查询:

from o in this.Session.Query<Order>
select new  { Amount = o.OrderAmount, Customer = o.Customer.GetCard() };
this.Session.Query中的来自o的

选择new{Amount=o.OrderAmount,Customer=o.Customer.GetCard()};

目前,您要求的东西不容易实现,因为为了处理投影,NHibernate使用HQL之外的ClientSideResultOperator(请参见
。VisitSelectClause
方法)

例如,下面的查询

var q = from c in this.Session.Query<Customer>()
        select new Card
        {
            FirstName = c.FirstName,
            LastName = c.LastName,
            FullName = c.FirstName + " " + c.LastName
        };
查询将转换为

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
            }) 
        };
var q=this.Session.Query()中的c
选择新的
{ 
Id=c.Id,
信息卡=新卡
{
FirstName=c.FirstName,
LastName=c.LastName,
全名=c.FirstName+“”+c.LastName
}) 
};

目前,您要求的东西不容易实现,因为为了处理投影,NHibernate使用HQL之外的ClientSideResultOperator(请参见
。VisitSelectClause
方法)

例如,下面的查询

var q = from c in this.Session.Query<Customer>()
        select new Card
        {
            FirstName = c.FirstName,
            LastName = c.LastName,
            FullName = c.FirstName + " " + c.LastName
        };
查询将转换为

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
            }) 
        };
var q=this.Session.Query()中的c
选择新的
{ 
Id=c.Id,
信息卡=新卡
{
FirstName=c.FirstName,
LastName=c.LastName,
全名=c.FirstName+“”+c.LastName
}) 
};

我是这样做的,但在第三位写同一段代码并不有趣;)@诺瓦科夫看到了更新。希望这会有所帮助。稍后我将尝试回答原始问题。谢谢,我将尝试使用DelegateDecompiler解决方案,它看起来很不错:)我是这样做的,但在第三位编写相同的代码并不有趣;)@诺瓦科夫看到了更新。希望这会有所帮助。稍后我将尝试回答原始问题。谢谢,我将尝试使用DelegateDecompiler解决方案,它看起来很不错:)
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
        };
}
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
            }) 
        };