2014-12-13 2 views
3

Я интерфейс, определенный следующим образом:Уплотненного Func <T, object> в методе Generic Extension

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 в качестве свойства IQueryable<T> с моего IEntityUnitOfWork, которое я хочу ссылаться в следующих утверждениях?

ответ

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)'. Вы также можете переименовать этот параметр: он больше не запрашивается. – hvd

+0

@hvd, Приятно знать, спасибо. Можете ли вы разъяснить, что «больше не запрашивается»? Это говорит о том, что это было, но теперь это не так? –

+1

Вы изначально имели 'IQueryable theQueryable', и в этом случае он действительно доступен для запроса. Когда у вас есть 'Func <..., IQueryable >' у вас нет запроса, у вас есть функция, которая при вызове возвращает запрос. – hvd

Смежные вопросы