Как запросить коллекцию объектов с использованием пользовательских условий? - PullRequest
0 голосов
/ 28 октября 2010

Извините, если это немного абстрактно.Я на начальной стадии разработки.

У меня есть два типа объектов:

  1. Объект, который должен хранить ряд определенных пользователем условий.
  2. Объект, который соответствует нулю или более условий, определенных в первом объекте.

Вот простой пример того, как он будет работать.

  1. Пользователь создает несколько объектов:введите 2 и добавьте их в коллекцию.
  2. Затем пользователь создает объект типа 1 и назначает ему несколько условий.
  3. Система использует условия в типе объекта 1 для создания спискаобъектов типа 2, отсортированных по процентам условий, которым соответствует каждый объект.

Вот пример ожидаемого вывода:

Conditions                                            List
Quantity >= 2                                         Object5 100%
Value < 2                                             Object2  75%
Category = "Blah"                                     Object4  50%
Quality > 5                                           Object1  25%
                                                      Object3   0%

Первый операнд в каждом условииимя свойства, в то время как второй операнд является значением этого свойства.

Как я могу это сделать?

Моя первая мысль, что это выглядит какязык запросов.Если бы они были записями в таблице БД, я мог бы соединить строку SQL для каждого условия, выполнить каждый запрос и подсчитать, сколько раз каждый идентификатор записи появлялся в результатах запроса.Но это простые старые объекты C #.Я еще не определился с тем, что использовать для сохранения объектов, поэтому на данном этапе я бы предпочел не привязывать себя к движку БД.Есть предложения?

Ответы [ 4 ]

1 голос
/ 28 октября 2010

Звучит так: LINQ - это то, что вы хотите использовать.В частности, я хотел бы изучить LINQ To Objects и LINQ To SQL , если в конечном итоге будет выбрано хранилище постоянства.

0 голосов
/ 28 октября 2010

Вы можете сделать это с помощью модифицированной версии Спецификации .Начните с интерфейса, который выражает результаты в процентах:

public interface ISpecification<T>
{
    double GetPercentSatisfiedBy(T target);
}

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

public sealed class Specification<T> : ISpecification<T>
{
    private readonly Func<T, bool> _predicate;

    public Specification(Func<T, bool> predicate)
    {
        _predicate = predicate;
    }

    public double GetPercentSatisfiedBy(T target)
    {
        return _predicate(target) ? 1 : 0;
    }
}

Теперь создайте спецификацию, которая линейно объединяет результатыдругих спецификаций:

public sealed class CompositeSpecification<T> : ISpecification<T>
{
    private readonly IList<ISpecification<T>> _specifications;

    public CompositeSpecification(params ISpecification<T>[] specifications)
    {
        _specifications = specifications.ToList();
    }

    public double GetPercentSatisfiedBy(T target)
    {
        return _specifications.Average(
            specification => specification.GetPercentSatisfiedBy(target));
    }
}

Наконец, создайте спецификацию, которая содержит все ваши требуемые условия, и примените ее к списку Foo объектов:

var specification = new CompositeSpecification<Foo>(
    new Specification<Foo>(foo => foo.Quantity >= 2),
    new Specification<Foo>(foo => foo.Value < 2),
    new Specification<Foo>(foo => foo.Category == "Blah"),
    new Specification<Foo>(foo => foo.Quality > 5));

var foos = new List<Foo> { ... };

var results =
    from foo in foos
    let percentSatisfied = specification.GetPercentSatisfiedBy(foo)
    orderby percentSatisfied descending
    select new
    {
        Foo = foo,
        PercentSatisfied = percentSatisfied
    };

Этот дизайн поддерживает спецификациипроизвольной сложности.

0 голосов
/ 28 октября 2010

Вот пример реализации, использующей LINQ-to-Objects для строк:

var conditions = new Func<string, bool>[]
{
    s => s.Length < 4,                  // less than 4 characters
    s => s.Count(c => c == 'o') > 2,    // more than 2 'o's
    s => s == "fooo",                   // is "fooo"
    s => s.Contains('b'),               // contains 'b'
};
var words = new[] { "foo", "fooo", "foooo", "bar", "barr", "bazooo" };
var query = words.Select(Word => new
                                 {
                                     Word,
                                     Percentage = conditions.Average(c => c(Word) ? 1M : 0M)
                                 })
                 .Where(p => p.Percentage > 0)          // keep words matches some conditions
                 .OrderByDescending(p => p.Percentage)  // order by the percentage
                 .ThenBy(p => p.Word);                  // then order in alphabetical order

Оглядываясь назад, я думаю, что этот пример может работать и с LINQ-to-SQL (с некоторыми изменениями в conditionsмассив).

Это был только быстрый пример, но вы, конечно, можете расширить эту идею еще больше.

0 голосов
/ 28 октября 2010

также есть статья о , как напрямую выполнять SQL-запросы (LINQ to SQL)

Northwnd db = new Northwnd(@"c:\northwnd.mdf");
IEnumerable<Customer> results = db.ExecuteQuery<Customer>
(@"SELECT c1.custid as CustomerID, c2.custName as ContactName
    FROM customer1 as c1, customer2 as c2
    WHERE c1.custid = c2.custid"
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...