如何使用LINQ和Reflection </t>过滤List <t>

时间:2014-08-22 10:12:37

标签: c# linq list generics reflection

我通过反射获取属性,我这样做是为了迭代列表。

private string HandleListProperty(object oldObject, object newObject, string difference, PropertyInfo prop)
{

   var oldList = prop.GetValue(oldObject, null) as IList;
   var newList = prop.GetValue(newObject, null) as IList;

   if (prop.PropertyType == typeof(List<DataModel.ScheduleDetail>))
   {
      List<DataModel.ScheduleDetail> ScheduleDetailsOld = oldList as List<DataModel.ScheduleDetail>;
      List<DataModel.ScheduleDetail> ScheduleDetailsNew = newList as List<DataModel.ScheduleDetail>;

      var groupOldSchedules = ScheduleDetailsOld
                             .GroupBy(x => x.HomeHelpID)
                             .SelectMany(s => s.DistinctBy(d => d.HomeHelpID)
                             .Select(h => new { h.HomeHelpID, h.HomeHelpName }));

      var groupNewSchedules = ScheduleDetailsNew
                             .GroupBy(x => x.HomeHelpID)
                             .SelectMany(s => s.DistinctBy(d => d.HomeHelpID)
                             .Select(h => new { h.HomeHelpID, h.HomeHelpName }));

     var AddedHomeHelp = string.Join(",", groupNewSchedules
                        .Where(x => x.HomeHelpID != null && !groupOldSchedule
                        .Any(y => y.HomeHelpID == x.HomeHelpID))
                        .Select(x => "\"<strong>" + x.HomeHelpName + "\"</strong>"));

     var RemovedHomeHelp = string.Join(",", groupOldSchedules
                          .Where(x => x.HomeHelpID != null && groupNewSchedules
                          .Any(y => y.HomeHelpID != x.HomeHelpID))
                          .Select(x => "\"<strong>"+x.HomeHelpName+"\"</strong>"));

   difference += string.IsNullOrWhiteSpace(RemovedHomeHelp) ? string.Empty : "<strong>HomeHelp</strong> " + RemovedHomeHelp + " Removed<br/>";

   difference += string.IsNullOrWhiteSpace(AddedHomeHelp) ? string.Empty : "<strong>HomeHelp</strong> " + AddedHomeHelp + "Added<br/>";
   }
}

现在我正在制作它是通用的,因为会有不同类型的列表,我不想放置if条件这样我想写 用于处理任何类型列表的通用代码。

我想出了这样的方式:

private void HandleListProperty(object oldObject, object newObject, string difference, PropertyInfo prop)
{

   var oldList = prop.GetValue(oldObject, null) as IList;
   var newList = prop.GetValue(newObject, null) as IList;

   var ListType = prop.PropertyType; 
   var MyListInstance = Activator.CreateInstance(ListType);

   MyListInstance = oldList;            
}

我能够获取MyListInstance中的项目,但由于类型将在运行时出现,我没有得到如何编写linq查询来过滤它们,任何想法如何做。

1 个答案:

答案 0 :(得分:1)

您想要比较列表。据我了解,你比较的2个列表总是属于同一类型,但有一次它可能是2个X列表,另一个时间可能是2个Y列表。

LINQ Except方法非常适用于此。默认情况下,它会比较项目是否与完全相同的引用但使用自定义比较器,它可以根据ID属性或您想要的任何其他内容进行比较。

您需要确定如何将2个项目视为相等,并创建一个实现IEqualityComparer<T>的自定义比较器,如下所示。

public class CompareSchedules : IEqualityComparer<ScheduleDetail>
{

    public bool Equals(ScheduleDetail x, ScheduleDetail y)
    {
        return x.HomeHelpID == y.HomeHelpID;
    }

    public int GetHashCode(ScheduleDetail obj)
    {
        return obj.HomeHelpID;
    }
}

public static class SuperDuperListComparer
{
    public class ListCompareResults<T>
    {
        public List<T> RemovedItems { get; set; }
        public List<T> AddedItems { get; set; }
    }

    public static ListCompareResults<T> CompareLists<T>(IList<T> list1, IList<T> list2, IEqualityComparer<T> comparer)
    {
        var addedItems = list2.Except(list1, comparer).ToList();
        var removedItems = list1.Except(list2, comparer).ToList();
        return new ListCompareResults<T>
        {
            AddedItems = addedItems,
            RemovedItems = removedItems
        };
    }

    public static ListCompareResults<T> CompareLists<T>(IList<T> list1, IList<T> list2)
    {
        return CompareLists<T>(list1, list2, EqualityComparer<T>.Default);
    }
}

这是一些示例代码。

    [TestMethod]
    public void TestListComparer()
    {
        var list1 = new List<ScheduleDetail> { 
            new ScheduleDetail { HomeHelpID = 1},
            new ScheduleDetail { HomeHelpID = 3}
        };

        var list2 = new List<ScheduleDetail> { 
            new ScheduleDetail { HomeHelpID = 1},
            new ScheduleDetail { HomeHelpID = 5}
        };


        var comparison = SuperDuperListComparer.CompareLists(list1, list2, new CompareSchedules());


    }


    public class ScheduleDetail
    {
        public int HomeHelpID { get; set; }

    }