Можно ли иметь массив параметров из Func - PullRequest
4 голосов
/ 15 февраля 2012

Возможно ли что-то похожее на следующую конструкцию?

  public IQueryable<T> AllWithFetch<TRelated>(IQueryable<T> existing, params Expression<Func<T, TRelated>>[] fetchExpressions)
  {
     return fetchExpressions.Aggregate(existing, (current, exp) => current.Fetch(exp));
  }

Который затем можно было бы назвать так ...

var allDetails = this.preGrantDetailRepository
                .AllWithFetch(this.preGrantDetailRepository.All, x => x.Case, x => x.CaseOwner)

В основном я пытаюсь включить добавление стратегий выборкидля NHibernate в наш абстрактный репозиторий, чтобы мы могли указывать эти стратегии с нашего логического уровня, не нарушая шаблон репозитория.Например, если мы перешли с NHibernate на другой ORM, мы можем предоставить те же методы хранилища, но реализованные для этого ORM.

Проблема возникает, когда я пытаюсь соединить несколько функций в массиве параметров.

Так что это работает ...

var allDetails = this.preGrantDetailRepository
                .AllWithFetch(this.preGrantDetailRepository.All, x => x.Case)

Но это не так, если "аргументы типа не могут быть выведены из их использования" messge

var allDetails = this.preGrantDetailRepository
                .AllWithFetch(this.preGrantDetailRepository.All, x => x.Case, x => x.CaseOwner)

Я использую.NET 3.5, Шаблон репозитория, Свободный NHibernate, SQL Server 2008

РЕДАКТИРОВАТЬ

Я решил проблему с помощью ответов Porges ниже, поэтому я принял ее,Проблема возникла из-за неправильного использования TRelated.Вот рабочий метод в хранилище ...

public IQueryable<T> AllWithFetch<T>(IQueryable<T> existing, params Expression<Func<T, Entity>>[] fetchExpressions)
        {
            return fetchExpressions.Aggregate(existing, (current, exp) => current.Fetch(exp));
        }

Теперь AllWithFetch не TRelated, и я использую суперкласс двух сущностей (Case & CaseOwner) в Func.

Спасибо за вашу помощь, ребята

Ответы [ 2 ]

4 голосов
/ 15 февраля 2012

Проблема в том, что вы TRelated, это не имеет ничего общего с params конкретно.

Попробуйте это, например:

void DoSomething<T,U>(Func<T,U> f, Func<T,U> f2)
{
}

void Main()
{
    DoSomething((int x) => x + 1, (int x) => x + ""); 
}

Компилятор выведет, что T должно быть int, но он не может определить хороший тип для U (я не уверен в деталях точных , но он обычно выиграл ' ищите тип выше по цепочке наследования).

Чтобы заставить его работать, вам нужно указать суперкласс; в этом случае object:

void Main()
{
    DoSomething<int,object>((int x) => x + 1, (int x) => x + ""); 
}

Так что вам нужно либо указать суперкласс самостоятельно (похоже, здесь будет object), либо просто избавиться от параметра TRelated.

2 голосов
/ 15 февраля 2012

Вы должны иметь TRelated в качестве возвращаемого значения для каждой функции..Case и .CaseOwner имеют одинаковый тип?Если нет, вы можете использовать

Func<T, object> 

вместо (или любой интерфейс)

...