Я должен согласиться с Лириком здесь.В терминах .Net использование объектов для ваших данных и LINQ для запроса их коллекции должно быть одним из самых быстрых способов сделать то, о чем вы просите, но при этом иметь в своем распоряжении богатый язык запросов.
ЕслиВас беспокоит размер коллекции, и если вы сможете хранить всю информацию в памяти, вы можете обратиться к таким проектам, как Memcached , чтобы помочь вам.
ОБНОВЛЕНИЕ
Я построил пример использования Linq с объектом критерия для запроса списка продуктов (хотя это может легко быть база данных Linq to Sql)
Сначалапример класса продукта:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Linq_Question
{
public class Product
{
public enum Categories
{
CatOne,
CatTwo,
CatThree
}
public int Id { get; set; }
public string Name { get; set; }
public Categories Category { get; set; }
public decimal Price { get; set; }
}
}
Теперь пример класса Критерии продукта
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Linq_Question
{
public class ProductCriteria
{
public Product.Categories? WhereCategoryIs { get; set; }
public decimal? WherePriceIsGreaterThan { get; set; }
public decimal? WherePriceIsLessThan { get; set; }
public string WhereNameContains { get; set; }
public ProductCriteria()
{
}
}
}
Пример репозитория - с использованием списков
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace Linq_Question
{
public class ProductRepository
{
private List<Product> products;
public ProductRepository()
{
products = new List<Product>();
products.Add(new Product() { Category = Product.Categories.CatOne, Id = 1, Name = "Product 1", Price = 100 });
products.Add(new Product() { Category = Product.Categories.CatTwo, Id = 2, Name = "Product 2", Price = 120 });
products.Add(new Product() { Category = Product.Categories.CatThree, Id = 3, Name = "Product 3", Price = 300 });
products.Add(new Product() { Category = Product.Categories.CatOne, Id = 4, Name = "Product 4", Price = 400 });
products.Add(new Product() { Category = Product.Categories.CatTwo, Id = 5, Name = "Product 5", Price = 500 });
products.Add(new Product() { Category = Product.Categories.CatThree, Id = 6, Name = "Product 6", Price = 600 });
}
public IEnumerable<Product> Retrieve(ProductCriteria criteria)
{
return this.products.Where(FilterProducts(criteria));
}
private Func<Product, bool> FilterProducts(ProductCriteria criteria)
{
Expression<Func<Product, bool>> predicate = PredicateBuilder.True<Product>();
List<IProductFilter> filters = new List<IProductFilter>();
filters.Add(new PriceIsGreaterThanFilter());
filters.Add(new CategoryFilter());
foreach (var item in filters)
{
if (item.IsValidFilter(criteria))
{
predicate = predicate.And(item.ApplyFilter(criteria));
}
}
return predicate.Compile();
}
}
}
Обратите внимание в методе FilterProducts, чтосписок фильтров зацикливается на каждом, проверяется, является ли он действительным фильтром с учетом текущего объекта критериев, а затем применяется при необходимости.
Вот интерфейс IProductFilter и некоторые примеры фильтров
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace Linq_Question
{
public interface IProductFilter
{
bool IsValidFilter(ProductCriteria criteria);
Expression<Func<Product, bool>> ApplyFilter(ProductCriteria criteria);
}
public class CategoryFilter : IProductFilter
{
public bool IsValidFilter(ProductCriteria criteria)
{
return (criteria.WhereCategoryIs.HasValue);
}
public Expression<Func<Product, bool>> ApplyFilter(ProductCriteria criteria)
{
return (p => p.Category == criteria.WhereCategoryIs.GetValueOrDefault());
}
}
public class PriceIsGreaterThanFilter : IProductFilter
{
public bool IsValidFilter(ProductCriteria criteria)
{
return (criteria.WherePriceIsGreaterThan.HasValue);
}
public Expression<Func<Product, bool>> ApplyFilter(ProductCriteria criteria)
{
return (p => p.Price > criteria.WherePriceIsGreaterThan.GetValueOrDefault());
}
}
}
Обратите внимание, что вам понадобится класс PredicateBuilder - найдено http://www.albahari.com/nutshell/predicatebuilder.aspx
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
namespace Linq_Question
{
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
}
}
Наконец, вотнебольшое консольное приложение, показывающее идею в действии:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Linq_Question
{
class Program
{
static void Main(string[] args)
{
ProductRepository repo = new ProductRepository();
Console.WriteLine("Items over 100");
foreach (var item in repo.Retrieve(new ProductCriteria() { WherePriceIsGreaterThan = 100 }))
{
Console.WriteLine(string.Format("Name {0}, Category {1}, Price {2}", item.Name, item.Category, item.Price));
}
Console.WriteLine("Items with a Category of Two");
foreach (var item in repo.Retrieve(new ProductCriteria() { WhereCategoryIs = Product.Categories.CatTwo }))
{
Console.WriteLine(string.Format("Name {0}, Category {1}, Price {2}", item.Name, item.Category, item.Price));
}
Console.Read();
}
}
}
Вы можете расширить эту идею, чтобы добавить несколько фильтров и даже работать, если функция, возвращаемая из IProductFilter, должна быть И или ИЛИ для выражения,
Фильтры могут быть введены в хранилище, что позволяет легко их менять во время выполнения.
Надеюсь, это даст вам некоторые идеи.