Как инициализировать пустую временную переменную, не имея прямого доступа к ее типу

Предположим, у меня есть следующий класс и объекты:

class Product
{ 
   public int ProductId { get; set; }
   public string ProductDesc { get; set; }
} 

string[] keywordArray = new string []{"A", "B", "C", "D"};    

var products = repository.GetAllProducts();

Я использую var, потому что GetallProducts() возвращает IQueryable<Product>, но я не могу "видеть" тип Product, так как он определен в моем DAL.

Теперь мне нужна временная переменная tempResult для хранения временных результатов в файле foreach. Например:

foreach(var keyword in keywordArray)
{
    tempResult = tempresult.Union(products.Where(p => p.ProductDesc.Contains(keyword)));
}

Если я объявлю var tempResult внутри foreach, он перезаписывается на каждой итерации (и это выдаст ошибку времени компиляции, поскольку его нельзя использовать до его инициализации).

Поэтому мне нужно инициализировать его вне foreach. Если я использую:

var tempResult = products;

Внутри моего foreach я просто суммирую весь набор желаемого набора результатов.

Поэтому возможны только два решения:

1) Создайте в репозитории метод, возвращающий пустой IQueryable<Product> (заводской шаблон)

2) Используйте отражение (если это возможно, но пока не уверен)

Я нашел оба решения немного «грязными». Есть ли другой подход/шаблон для достижения этой цели? Спасибо


person CiccioMiami    schedule 29.03.2012    source источник
comment
добавьте оператор using для вашего пространства имен Product (вы обращаетесь к его членам, вам это понадобится).   -  person Alex    schedule 29.03.2012
comment
@alex Вы можете обойтись без оператора using, если вы просто, например. чтение свойств внутри лямбды; вам это нужно только в том случае, если вам нужно ссылаться на класс где-то по имени, например. конструктор, объявление переменной и т.д.   -  person Rawling    schedule 29.03.2012


Ответы (3)


Ваш код должен «видеть» тип Product, так как вы обращаетесь к ProductDesc и так далее.

Вам просто нужно добавить оператор using для пространства имен вашего DAL или, в худшем случае, установить tempResult в Enumerable.Empty<My.DAL.Namespace.Product>();

Нет необходимости создавать целый метод только для того, чтобы избежать ссылки на пространство имен; использование отражения еще хуже.

Если подумать, просто позвони

var notTempResult = keywordArray.SelectMany(
    kw => products.Where(p => p.ProductDesc.Contains(kw)).Distinct();

чтобы получить результат, даже не ссылаясь на пространство имен.

person Rawling    schedule 29.03.2012
comment
Спасибо, но я немного запутался. В соответствии с единицей работы из моего сервисного уровня я не могу использовать переменные, определенные в моем DAL, верно? - person CiccioMiami; 29.03.2012
comment
Я не уверен, что вы имеете в виду здесь. Нет никаких основанных на коде причин, по которым это не должно работать. - person Rawling; 29.03.2012
comment
Понятия не имею о вашей архитектуре. Как вы предлагаете получить что-либо из вашего DAL, если вы не можете использовать определенные в нем классы? - person Rawling; 30.03.2012

Один из вариантов — объявить ваш tempResult как IList и использовать .ToList() в объединении IEnumerable.

        string[] keywordArray = new string[] {"A", "B", "C", "D"};

        var products = repository.GetAllProducts();

        IList<Product> tempResult = new List<Product>();
        foreach (var keyword in keywordArray)
        {
            //declared because of access to modified closure issue.
            string keyword1 = keyword;
            tempResult = tempResult.Union(products.Where(p => 
               p.ProductDesc.Contains(keyword1))).ToList();
        }
person alan    schedule 29.03.2012
comment
Если спрашивающий не может использовать IQueryable<Product>, он не сможет использовать IList<Product> или List<Product>. - person Rawling; 29.03.2012
comment
О да. Я пропустил эту часть. Я думал, что это казалось слишком простым: P - person alan; 29.03.2012
comment
Затем я бы попытался изменить дизайн ваших репозиториев, чтобы они не возвращали IQueryable‹›. Многие считают это плохой практикой. stackoverflow.com/questions/7322434/ - person alan; 29.03.2012
comment
ну проблема в том, что у меня много данных, и мне нужно использовать IQueryable, чтобы не занимать слишком много памяти. Я заполняю коллекцию после того, как вся фильтрация завершена. Единственным недостатком является то, что я не могу использовать методы LINQtoObjects в IQueryable. - person CiccioMiami; 29.03.2012

Может быть, вы можете использовать выражение linq и вам не нужно использовать какую-либо временную переменную.

 var result = products.Where(p => keywordArray.Contains(p.ProductDesc));
person Prakash    schedule 29.03.2012