C# 如何筛选列表<;T>;带LINQ和反射
我通过反射获得属性,我这样做是为了在列表上迭代C# 如何筛选列表<;T>;带LINQ和反射,c#,linq,list,generics,reflection,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;
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/>";
}
}
我能够在MyListInstance中获取项目,但由于类型将在运行时出现,我不知道如何编写linq查询来过滤它们,也不知道如何进行过滤。您想要比较列表。据我所知,您所比较的两个列表始终是同一类型的,但一次可能是两个X列表,另一次可能是两个Y列表 LINQ Except方法非常适合于此。默认情况下,如果项目是相同的精确引用,它将进行比较,但使用自定义比较器,它可以基于ID属性或任何其他您想要的内容进行比较
您需要确定如何考虑2个项目是相等的,并创建一个定制的比较器,实现如下代码< IEqualityComparer >代码>
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);
}
}
公共类比较计划:IEqualityComparer
{
公共布尔等于(明细表x,明细表y)
{
返回x.HomeHelpID==y.HomeHelpID;
}
公共int GetHashCode(ScheduleDetail obj)
{
返回obj.HomeHelpID;
}
}
公共静态类SuperDuperListComparer
{
公共类ListCompareResults
{
公共列表RemovedItems{get;set;}
公共列表加法器{get;set;}
}
公共静态列表比较结果比较列表(IList列表1、IList列表2、IEqualityComparer比较程序)
{
var addedItems=list2.Except(list1,comparer.ToList();
var removedItems=list1.Except(list2,comparer.ToList();
返回新的ListCompareResults
{
AddedItems=AddedItems,
RemovedItems=RemovedItems
};
}
公共静态ListCompareResults比较列表(IList list1、IList list2)
{
返回比较列表(列表1、列表2、EqualityComparer.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; }
}
[TestMethod]
公共void TestListComparer()
{
var list1=新列表{
新的ScheduleDetail{HomeHelpID=1},
新的ScheduleDetail{HomeHelpID=3}
};
var list2=新列表{
新的ScheduleDetail{HomeHelpID=1},
新的ScheduleDetail{HomeHelpID=5}
};
var comparison=SuperDuperListComparer.CompareLists(列表1,列表2,新的CompareSchedules());
}
公共类时间表详细信息
{
公共int HomeHelpID{get;set;}
}
请在设置代码格式方面投入更多精力-目前很难阅读,缩进到处都是。如果我正确理解您的问题,我将向此方法传递一个委托函数以执行筛选。你的具体实现似乎做了一些非通用的事情,所以你不能把它放在那里。@AndreasMüller没有明白你的意思,你能详细说明一下吗?第一个问题:我不认为你所有的列表都有HomeHelpId
和HomeHelpName
属性,是吗?如果没有,您还需要传递这些属性(属性名)。@RaphaëlAlthaus当然DataModel.scheduledeail
有这些属性
[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; }
}