我问过这个question关于使用从通用集合中返回一个对象(First、Min、Max 等)的 Linq 方法。
我现在希望能够使用 linq 的 except() 方法,但我不知道该怎么做。也许答案就在我面前,但我认为我需要帮助。
我有一个通用方法,可以填充相应描述性字段的缺失日期。该方法声明如下:
public IEnumerable<T> FillInMissingDates<T>(IEnumerable<T> collection, string datePropertyName, string descriptionPropertyName)
{
Type type = typeof(T);
PropertyInfo dateProperty = type.GetProperty(datePropertyName);
PropertyInfo descriptionProperty = type.GetProperty(descriptionPropertyName);
...
}
我想要完成的就是这个。 datePropertyName 是我将用来填充日期间隙的日期属性的名称(为集合中尚未存在的日期添加默认对象实例)。如果我处理一个非泛型类,我会这样做:
foreach (string description in descriptions)
{
var missingDates = allDates.Except(originalData.Where(d => d.Description == desc).Select(d => d.TransactionDate).ToList());
...
}
但是,如何使用通用方法 FillInMissingDates 以及在运行时解析的 dateProperty 和 descriptionProperty 属性来执行相同的操作?
最佳答案
我认为最好的方法是定义一个包含您想要在方法中使用的所有属性的接口(interface)。让可能使用该方法的类实现该接口(interface)。然后,使用泛型方法并约束泛型类型从接口(interface)派生。
这个示例可能并不完全符合您的要求——它填充了列表中与描述匹配的项目的缺失日期,但希望它能为您提供基本的想法。
public interface ITransactable
{
string Description { get; }
DateTime? TransactionDate { get; }
}
public class CompletedTransaction : ITransactable
{
...
}
// note conversion to extension method
public static void FillInMissingDates<T>( this IEnumerable<T> collection,
string match,
DateTime defaultDate )
where T : ITransactable
{
foreach (var trans in collection.Where( t => t.Description = match ))
{
if (!trans.TransactionDate.HasValue)
{
trans.TransactionDate = defaultDate;
}
}
}
在调用之前,您需要将枚举转换为 ITransactable(至少在 C# 4.0 发布之前)。
var list = new List<CompletedTransaction>();
list.Cast<ITransactable>()
.FillInMissingDates("description",DateTime.MinValue);
或者,您可以使用 Dynamic LINQ 进行调查来自VS2008 Samples收藏。如果类之间不一致,这将允许您指定属性的名称。但是,您可能仍然需要使用反射来设置属性。
关于c# - 在泛型集合上使用 except(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1050456/