在一个通用扩展方法中嵌套了Func<T, object>。

3

我有一个定义如下的接口:

public interface IEntityUnitOfWork : IEntityModelUnitOfWork, IDisposable
{
    IQueryable<T> IncludeProperties<T>(IQueryable<T> theQueryable, params Func<T, object>[] toInclude)
        where T : class, new();
}

...这使我能够编写如下代码:

var foo = MyUnitOfWork.IncludeProperties(
    MyUnitOfWork.MyQueryable,
    p=>p.MyProperty1,
    p=>p.MyProperty2,
    ...
    p=>p.MyPropertyN);

在实现上添加一些技巧,这个工作得相当不错。但是它看起来有点别扭。我认为我应该能够更加简洁地编写它,以便可以使用这种格式:
var foo = MyUnitOfWork.Fetch(
    f=>f.MyQueryable,
    p=>p.MyProperty1,
    p=>p.MyProperty2,
    ...
    p=>p.MyPropertyN);

因此,我编写了一个如下所示的扩展方法:

public static IQueryable<T> Fetch<T>(
    this IEntityUnitOfWork unitOfWork,
    Func<IEntityUnitOfWork, IQueryable<T>> queryable,
    params Func<T, object>[] toInclude) where T:class, new()
{
    var q = queryable.Target as IQueryable<T>;
    foreach (var p in toInclude)
    {
        q = unitOfWork.IncludeProperties(q, new[] { p });
    }
    return q ;
}

这个建立过程很顺利,而且Intellisense也是我所期望的工作,但是当我试图使用它时,它却失败了,并显示了一个 NullReferenceException。 我假设 queryable.Target应该是我想引用的IQueryable<T>,但它似乎不是我所预想的东西,而在我的Intellisense / Quickwatch选项中没有其他明显的选择。

我该如何将那个q值设置为我想要在以下语句中引用的IEntityUnitOfWorkIQueryable<T>属性?

1个回答

2

经过更多的调试,看起来我不需要函数的 Target 属性,而是需要 Invoke() 方法:

var q = queryable.Invoke(unitOfWork);

经过一些优化,我将它改成了这个样子:

public static IQueryable<T> Fetch<T>(
    this IEntityUnitOfWork unitOfWork,
    Func<IEntityUnitOfWork, IQueryable<T>> queryable,
    params Func<T, object>[] toInclude) where T : class, new()
{
    var q = queryable.Invoke(unitOfWork);
    return unitOfWork.IncludeProperties(q, toInclude);
}

......这样做正好符合预期。


2
这确实是有效的,但传统的写法只是 queryable(unitOfWork)。您可能还想重新命名该参数:它不再是一个可查询的对象。 - user743382
@hvd,好的了解,谢谢。您能详细说明一下“不再是可查询的”吗?这意味着它曾经是可查询的,但现在不是了? - Jeremy Holovacs
1
你最初有一个 IQueryable<T> theQueryable,在这种情况下,它确实是可查询的。当你有 Func<..., IQueryable<T>> 时,你没有一个可查询的对象,而是一个函数,当调用时返回一个可查询的对象。 - user743382

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接