我定义了许多对象,每个对象都有一个名为“CreateDate”的属性。
是否可以编写单个通用方法从我指定的对象中选择最高日期?
我试图对此使用通用方法,但是当我尝试指定属性名称时编译器不喜欢它。
我试图在这些方面取得成就......
private static DateTime GetLastDate<T>(List<T> data)
{
// Unfortunately, this is not allowed...
return
(from d in data
orderby d.CreateDate
select d.CreateDate).FirstOrDefault();
}
答案 0 :(得分:10)
最好的方法是创建一个具有特定功能的接口,并让所有类实现该接口:
public interface ICreated
{
public DateTime CreateDate {get;}
}
然后,您可以确保接受的所有项目都实现该接口:
private static DateTime GetLastDate<T>(IEnumerable<T> input) where T : ICreated
{
return input.Max(d=>d.CreateDate);
}
如果那不是一个选项(可能是因为你无法修改类以使其实现接口或集合来包装基础类型),那么可以使用dynamic
。我非常不鼓励你这样做,因为它真的不是很好的设计,它会慢得多,而且很容易破坏,但它可以工作:
private static DateTime GetLastDate(IEnumerable<dynamic> input)
{
return input.Max(d=>d.CreateDate);
}
答案 1 :(得分:2)
您可以使用Reflection按字符串值获取属性名称,如下所示:
你需要这个方法来获取字符串值的实际属性,如果你打算使用你可能感兴趣的一些通用的东西,你可以将它放在某个地方,你可以重复使用它。
// Add ' using System.Reflection; ' on top
public static object GetPropertyValue(object o, string propertyName)
{
Type type = o.GetType();
PropertyInfo info = type.GetProperty(propertyName);
object value = info.GetValue(o, null);
return value;
}
使用该方法,您可以执行此操作,而不是不适合您的代码:
private static DateTime GetLastDate<T>(List<T> data)
{
object value = (from d in data
orderby GetPropertyValue(d, "CreateDate")
select GetPropertyValue(d, "CreateDate")).FirstOrDefault();
return DateTime.Parse(value.ToString());
}
它现在应该可以正常工作,并且它将按照您希望的方式保持通用。
答案 2 :(得分:1)
您可以将CreateDate属性封装在基类(例如BaseClass)中并像这样执行
private static DateTime GetLastDate<T>(List<T> data) where T : BaseClass
{
...
}
答案 3 :(得分:1)
我只是这样做并在我的扩展类
中创建了一个泛型方法 public static object GetPropertyValue(this object o, string propertyName)
{
Type type = o.GetType();
try
{
PropertyInfo info = (from x in type.GetProperties() where x.Name.ToLower() == propertyName.ToLower() select x).First();
object value = info.GetValue(o, null);
return value;
}
catch (Exception ex)
{
return default(object);
}
}
public static T GetFieldValue<T>(this object o, string propertyName) where T : struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>
{
try
{
var val = GetPropertyValue(o, propertyName);
return (T)val;
}
catch (Exception ex)
{
return default(T);
}
}
这就是我用它的方式......
var max_cust_id = (string)(from m in final_list.Skip((int)offset)
orderby m.GetPropertyValue(identityField)
select m.GetPropertyValue(identityField)).Max();