代码之家  ›  专栏  ›  技术社区  ›  Zacho

如何使用同一类的对象过滤泛型列表

  •  1
  • Zacho  · 技术社区  · 17 年前

    我在网上搜索了一下这个答案,问了几个开发人员,但都没有找到答案。我有一个名为StaffingPositionsDataContract的类,我正在将模拟数据(目前)加载到一个列表中<&燃气轮机;回到一页。这工作得很好,但是现在我需要根据屏幕上输入的值的另一个列表过滤列表,作为JSON发送到此服务,然后反序列化为同一类的列表。请注意,用户可以对这些类成员中的任何一个进行筛选,因此所有成员都可以为null,或者一个成员可以为null,等等。 服务方法如下:

       public List<StaffingPositionsDataContract> GetStaffingPosition(string searchFilters)
        {
            var filters = JsonConvert.DeserializeObject<List<StaffingPositionsDataContract>>(searchFilters);
            IList<StaffingPositionsDataContract> contracts = new StaffingPositionsDataContract().LoadMockData();
    
            if (searchFilters.Length > 4)
            {
                //Filter contracts here!
            }
    
            return contracts;
        }
    

    下面是要加载模拟数据的数据协定类:

    [DataContract] [Serializable]
    public class StaffingPositionsDataContract
    {
        [DataMember(Order = 1)] public int PositionId { get; set; }
        [DataMember(Order = 2)] public string Series { get; set; }
        [DataMember(Order = 3)] public string BFY { get; set; }
        [DataMember(Order = 4)] public string BudgetStatus { get; set; }
        [DataMember(Order = 5)] public string DutyStation { get; set; }
        [DataMember(Order = 6)] public string OrgLocation { get; set; }
        [DataMember(Order = 7)] public string BudgetingEntity { get; set; }
        [DataMember(Order = 8)] public string SeriesTitle { get; set; }
        [DataMember(Order = 9)] public int PersonnelId { get; set; }
        [DataMember(Order = 10)] public string PositionStatus { get; set; }
        [DataMember] public int RecId { get; set; }
    
        public List<StaffingPositionsDataContract> LoadMockData()
        {
            List<StaffingPositionsDataContract> staffingposition = new List<StaffingPositionsDataContract>()
            {
                new StaffingPositionsDataContract() {RecId=1, PositionId = 12345, Series="", BFY="FY2010", BudgetStatus="Actual", DutyStation="", OrgLocation="", BudgetingEntity=""},
                new StaffingPositionsDataContract() {RecId=2, PositionId = 67891, Series="", BFY="FY2011", BudgetStatus="Actual", DutyStation="", OrgLocation="", BudgetingEntity=""},
                new StaffingPositionsDataContract() {RecId=3,PositionId = 12345, Series="", BFY="FY2010", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""},
                new StaffingPositionsDataContract() {RecId=4,PositionId = 67892, Series="", BFY="FY2011", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""},
                new StaffingPositionsDataContract() {RecId=5,PositionId = 987654, Series="", BFY="FY2010", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""}
            };
            return staffingposition;
        }
    }
    

    请注意,过滤器将始终是填充的一个、一些或所有值的列表。请保存我的理智和帮助如果你能!谢谢!

    我应该在前面提到,我真的希望这是一个泛型函数,可以被任何类似的数据类(有很多)使用。

    3 回复  |  直到 17 年前
        1
  •  1
  •   Cade Roux    17 年前

    我不会过滤你过滤的地方。我将把过滤器传递给集合的负载,并在那里内部使用它,方法是将这些条件传递给服务、数据库或类似的对象,或者在将每个对象添加到集合之前,强制每个对象根据这些条件验证自己。

    public List<StaffingPositionsDataContract> GetStaffingPosition(string searchFilters)
    {
        var filters = JsonConvert.DeserializeObject<List<StaffingPositionsDataContract>>(searchFilters);
        IList<StaffingPositionsDataContract> contracts = new StaffingPositionsDataContract().LoadMockData(searchFilters);
    
        return contracts;
    }
    
    [DataContract] [Serializable]
    public class StaffingPositionsDataContract
    {
        [DataMember(Order = 1)] public int PositionId { get; set; }
        [DataMember(Order = 2)] public string Series { get; set; }
        [DataMember(Order = 3)] public string BFY { get; set; }
        [DataMember(Order = 4)] public string BudgetStatus { get; set; }
        [DataMember(Order = 5)] public string DutyStation { get; set; }
        [DataMember(Order = 6)] public string OrgLocation { get; set; }
        [DataMember(Order = 7)] public string BudgetingEntity { get; set; }
        [DataMember(Order = 8)] public string SeriesTitle { get; set; }
        [DataMember(Order = 9)] public int PersonnelId { get; set; }
        [DataMember(Order = 10)] public string PositionStatus { get; set; }
        [DataMember] public int RecId { get; set; }
    
        public List<StaffingPositionsDataContract> LoadMockData(string searchfilters)
        {
            // filter the list returned here
    
            List<StaffingPositionsDataContract> staffingposition = new List<StaffingPositionsDataContract>()
            {
                new StaffingPositionsDataContract() {RecId=1, PositionId = 12345, Series="", BFY="FY2010", BudgetStatus="Actual", DutyStation="", OrgLocation="", BudgetingEntity=""},
                new StaffingPositionsDataContract() {RecId=2, PositionId = 67891, Series="", BFY="FY2011", BudgetStatus="Actual", DutyStation="", OrgLocation="", BudgetingEntity=""},
                new StaffingPositionsDataContract() {RecId=3,PositionId = 12345, Series="", BFY="FY2010", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""},
                new StaffingPositionsDataContract() {RecId=4,PositionId = 67892, Series="", BFY="FY2011", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""},
                new StaffingPositionsDataContract() {RecId=5,PositionId = 987654, Series="", BFY="FY2010", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""}
            };
            return staffingposition;
        }
    }
    
        2
  •  0
  •   Amy B    17 年前

    然后您可以比较属性以找到匹配项,这很容易。

    public class Customer
    {
        public int CustomerId { get; set; }
        public string Name { get; set; }
        public string FavoriteColor { get; set; }
    
        // probably a better way to do this
        // just writing fast for demo
        public XElement ToXElement()
        {
            List<XAttribute> attributes = new List<XAttribute>();
    
            if (this.CustomerId != 0)
                attributes.Add(new XAttribute("CustomerId", this.CustomerId));
            if (this.Name != null)
                attributes.Add(new XAttribute("Name", this.Name));
            if (this.FavoriteColor != null)
                attributes.Add(new XAttribute("FavoriteColor", this.FavoriteColor));
    
            XElement result = new XElement("Customer", attributes);
            return result;
        }
    }
    

    List<Customer> source = new List<Customer>()
    { new Customer(){ CustomerId=1, FavoriteColor="Blue", Name="Alex" },
      new Customer(){ CustomerId=2, FavoriteColor="Green", Name="Bob" },
      new Customer(){ CustomerId=3, FavoriteColor="Blue", Name="Cindy" },
      new Customer(){ CustomerId=4, FavoriteColor="Red", Name="Darren" }
    };
    List<Customer> examples = new List<Customer>()
    { new Customer(){ FavoriteColor="Blue", CustomerId = 3},
      new Customer(){ Name="Darren"}
    };
    
    List<XElement> sourceElements = source.Select(c => c.ToXElement()).ToList();
    List<XElement> exampleElements = examples.Select(c => c.ToXElement()).ToList();
    
    //and now the query...
    var query = sourceElements
      .Where(s => exampleElements
        .Any(ex => ex.Attributes()
          .All(exatt => s.Attribute(exatt.Name).Value == exatt.Value)
        )
      );
    
    foreach(XElement x in query)
      Console.WriteLine(x);
    

    也:

    • 如果您发送一个空示例(所有默认值),那么您将返回整个源代码列表。
    • 如果你没有发送任何示例(一个空列表),你什么也得不到。
        3
  •  0
  •   user1228 user1228    17 年前

    使用Linq,用一个列表过滤另一个列表非常简单:

    var foo = new int[]{1,2,3,4,5};
    var bar = new int[]{1,3,5};
    var result = from x in foo where !bar.Contains(x) select x;
    

    您只需要在数据契约中有一个Equals方法,它执行您的需求所要求的任何等价性测试。

    如果您的UI允许用户“创建”1到n个要筛选的契约,并且您将其作为契约的集合(无到所有的契约都可能为空),那么这仍然有效。


    针对扎乔的评论:

    var foo = new string[]{"1","2","3","4","5"}; 
    var bar = new string[]{"1","3",null,"5"};
    var result = from x in foo where !bar.Contains(x) select x;
    

    筛选器可枚举项bar包含空值。此功能有效。如果这个解决方案对你不起作用,扎乔,你就有另一个问题了。我猜这和平等比较有关。