0

对不起,如果这有点抽象。我正处于发展的早期阶段。

我有两种对象类型:

  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 字符串,运行每个查询并计算每个记录 ID 在查询结果中出现的次数。但这些都是普通的旧 C# 对象。我还没有决定使用什么来进行对象持久化,所以我现在不想将自己绑定到数据库引擎。有什么建议么?

4

4 回答 4

1

这听起来像LINQ是您想要使用的。特别是,如果最终选择持久性存储,我会研究LINQ To ObjectsLINQ To SQL 。

于 2010-10-28T04:29:44.037 回答
0

also, there is an article on how Directly Execute SQL Queries (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"
);
于 2010-10-28T04:36:00.183 回答
0

这是在字符串上使用 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数组进行了一些调整)。

这只是一个简单的示例,但您当然可以进一步扩展这个想法。

于 2010-10-28T05:01:26.233 回答
0

您可以使用规范模式的修改版本来做到这一点。从一个以百分比表示结果的界面开始:

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
    };

此设计支持任意复杂度的规范。

于 2010-10-28T05:21:47.580 回答