我问过这个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收藏。如果类之间不一致,这将允许您指定属性的名称。但是,您可能仍需要使用反射来设置属性。
