【问题标题】:Generic Expression Filter通用表达式过滤器
【发布时间】:2012-06-08 06:25:11
【问题描述】:

您好,我希望有人能够提供以下方面的一些指导:

我正在尝试创建一个使用反射的通用表达式过滤器,它可以接收一组规则并创建一个有效的表达式来限制从数据源返回的数据。

我遇到的问题是试图了解如何编写表达式来处理以下场景。

public class Item
{
    public string Name { get; set; }
    public List<TagTypes> TagTypes { get; set; }
}

public class TagTypes
{
    public string Name { get; set; }
    public List<Tags> Tags { get; set; }
}

public class Tags
{
    public string TagName { get; set; }
}

数据基本上看起来像

var itemList = new List<Item>
            {
                new Item
                {
                Name = "xyz",
                TagTypes = new List<TagTypes>
                    {
                        new TagTypes
                        {
                            Name = "Genre",
                            Tags = new List<Tags>
                                {
                                new Tags
                                    {
                                        TagName = "tag1"
                                    },
                                new Tags
                                    {
                                        TagName = "tag2"
                                    }        
                                }
                        }
                    }
               }

            };

我想写一个表达式,返回所有匹配'Genre'过滤器的项目-->'tag1'

我可以使用以下方法做到这一点:

var filtered = from item in itemList
from tagType in item.TagTypes
   where tagType.Name == "Genre"
      from tag in tagType.Tags
      where tag.TagName == "tag1"
select item

并且有一个基本的工作版本,可以很好地用于 Item 类的属性,但是我不知道如何在 TagTypes 及以下执行 SelectMany。

基础级别如下

var parameter = Expression.Parameter(typeof(T), "itemList");
var property = GetPropertyInfo<T>({Propertyname});
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
Expression.Equal(propertyAccess, Expression.Constant({Value}));

编辑

数据存储在 NoSQL 数据库中,过滤器是动态的,可以更改和添加。

使用反射创建通用过滤器的原因是为了适应不同的过滤器,而不必预先知道它们是什么。用户将能够使用过滤器 id 请求数据,然后这将根据请求中的过滤器选择数据。

【问题讨论】:

  • 为什么需要创建表达式?只需为 Name 和 TagName 使用变量。
  • @adrianm 创建表达式的需要来自于将查询传递给 NoSQL Linq 提供程序。数据库可能有 60K+ 记录,因为我不知道用户将过滤哪些属性似乎是最明智的解决方案
  • @adrianm 上面的结构是实际对象的缩减版
  • @SCB 创建过滤器的用户输入是什么,或者如果它们是“预定义的”,它们将如何构建?类似于要返回的项目类型,以及一种元组 property to filter-value(s) of the proeprty
  • SelectMany 只是表达式中的一个方法调用,这可能不是您想要的。我假设您的提供者实际上想要一个 IQueryable 而不是表达式。

标签: c# linq generics expression


【解决方案1】:

我认为您可能过于复杂了。

您可以只写一个Expression&lt;Func&lt;Item&gt;&gt;Expression&lt;Func&lt;List&lt;Item&gt;&gt; 并选择Body 属性。

例如

 Expression<Func<List<Item>> createListOfItems = () => new List<Item>
        {
            new Item
            {
            Name = "xyz",
            TagTypes = new List<TagTypes>
                {
                    new TagTypes
                    {
                        Name = "Genre",
                        Tags = new List<Tags>
                            {
                            new Tags
                                {
                                    TagName = "tag1"
                                },
                            new Tags
                                {
                                    TagName = "tag2"
                                }        
                            }
                    }
                }
           }

        };

【讨论】:

  • 我不是 100% 确定我正确地解释了自己。根据我的编辑,过滤器将驱动从无 SQL 数据库中检索哪些数据,直到运行时我才会知道用户请求了哪些属性或值。
  • @SCB,那么我们需要查看您的对象模型的架构
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-04
  • 2012-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多