2015-08-16 9 views
0

В LINQ to Objects, все равно, чтобы определить, какие объекты/объекты квалифицированы/дисквалифицированы на каждом из фильтров?Как перехватить фильтры Linq

Для например) Скажем, у меня есть объект под названием «Продукт» (Id, имя), и если я вход 100 Продукты в запрос Linq, который имеет 5 „где“ Conditon и получить 20 Продукты в качестве выходного сигнала.

Есть ли способ идентифицировать, какой продукт был отфильтрован, при каком условии?

+0

Спасибо за ответ – memumani

+0

Вы искали то, что искали? (Кроме того, похоже, что вы прокомментировали свой вопрос, а не на мой ответ: P) –

+0

Спасибо за ответ. Различные запросы в разных местах, где я хочу регистрировать такую ​​информацию. Вместо того, чтобы вносить изменения в несколько мест, есть какой-то жанрализованный подход, чтобы держать его в одном месте или с минимальными изменениями. – memumani

ответ

0

Важным аспектом остается то, что вы хотите сделать с отфильтрованными данными на каждом уровне, так как вы знаете, что linq для объектов использует механизм цепочки, где результат одного уровня подается в качестве входа на следующий уровень, некоторые из них:

var result = OriginalList.Where(Condition1) - Level1 
         .Where(Condition2) - Level2 
         .Where(Condition3) - Level3 
         .Where(Condition4) - Level4 

Здесь Выход Level1 является входом для Level2 и так далее. Если на определенном уровне нет данных, если будет обеспечено, чтобы следующий набор уровней был пропущен внутри страны, так как любое условие для пустого набора и пустое задано.

Для получения результата на каждом уровне, вы должны отделить их в отдельных переменных и сделать цепную самостоятельно, основываясь на условных требованиях, которые вы можете иметь, что-то вроде:

var result1 = OriginalList.Where(Condition1) 
var result2 = result1.Where(Condition2) 

Так на и и так далее, где перед применением предложения where в результате 1 вы можете применить условную проверку. Как я понимаю, вы можете стандартный регистратор для печати деталей в каждом из точки к югу, реализовать метод расширения следующим образом:

public static class LoggingExtension 
{ 
    public static void Log<dynamic>(IEnumerable<dynamic> collection) 
    { 
    // Use the favorite logger to log the collection here 
    } 
} 

Если я использую приведенный выше код для печати Result1, result2, что вам нужно является:

var result1 = OriginalList.Where(Condition1) 
     result1.Log(); 
    var result2 = result1.Where(Condition2) 
     result2.Log(); 

Я использую динамический тип в методе расширения выше, чтобы избежать выборок типа анонимного, внутренне вы можете ввести приведение к любому типу и использовать его в регистраторе

2

Это можешь, вероятно, быть обобщенным, но вы можете сделать это. Я просто не вижу варианта использования.

Используйте ToLookup(), чтобы разделить ваши запросы. «Дисквалифицированные» элементы будут сосредоточены под группой false, и вы можете продолжить свой запрос группой true.

например,

var numbers = Enumerable.Range(0, 100); 
var p1 = numbers.ToLookup(n1 => n1 < 50); 
// p1[false] -> [ 50, 51, 52, ... ] 
var p2 = p1[true].ToLookup(n2 => n2 % 2 == 0); 
// p2[false] -> [ 1, 3, 5, 7, ... ] 
var p3 = p2[true]... // and so on 
0

Пока все до сих пор показал вам, как сделать очевидную вещь, то есть группировать данные в кусках, соответствующих одному условию, никто не обращался, что вы на самом деле просят

определить, какой продукт был отфильтрован , в котором, когда условие

Жесткий q uestion is как будет регистрироваться, где условие?

Это может показаться тривиальным, но вы потерпите неудачу, потому что вы не сможете получить строковое представление используемого объекта Func. Это делегат, т.скомпилированный код, и вам придется перепроектировать его во время выполнения, чтобы получить исходный код. Это само по себе достаточно сложно, но если компилятор решил оптимизировать код, который вы потеряли.

Только если вы готовы создать свой собственный метод расширения (ы), которые используют выражения в смену Func s вы будете иметь возможность войти в состояние где, потому что выражение состоит из маркеров, которые могут быть легко «ToString-ed» во время выполнения.

Например:

public static IEnumerable<T> WhereEx<T>(this IEnumerable<T> sequence, Expression<Func<T, bool>> condition) 
{ 
    var logString = condition.Body.ToString(); 
    foreach (T item in sequence.Where(condition.Compile())) 
    { 
     yield return item; 
     // logging hook here, this one simply dumps in Linqpad. 
     string.Format("Item '{0}' meets '{1}'", item, logString).Dump(); 
    } 
} 

Теперь вы действительно улавливающий фильтр. Но вы не знаете, где в коде применяется фильтр. Если вы также хотите записывать кадры стека, производительность, скорее всего, станет проблемой (отражение!), Потому что она уже находится под давлением, каждый раз компилируя выражение. Затем ведение журнала должно быть асинхронной, включающей в себя потокобезопасную очередь протоколирования.

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