我有一个与这里回答的问题略有不同的问题(使用反射从列表中检索值)
虽然这里批准的答案适用于select,但我想扩展它,以便可以从基于条件类型的查询中获取数据。目前,我修改后的代码看起来像这个
public static async Task<T> GetDataFromTable<T>(string paramName, string condition="")
{
var k = Activator.CreateInstance(typeof(T));
var mn = typeof(T).GetProperty(paramName);
var tc = typeof(T).GetProperty(condition);
if (mn == null || !ftrackData.Online)
return (T)k;
var data = GetTableData<T>();
if (!string.IsNullOrEmpty(paramName))
{
var retval = data.Select(t => mn.GetValue(t, null));
return (T)retval;
}
else
return (T)data.FirstOrDefault(t => mn.GetValue(t, null) > tc.GetType(t, null)).ToList();
}
我希望在最后的返回中更改">",这取决于传递到参数列表中的附加参数。我知道我可以做一个简单的切换,但有没有办法通过插入来改变条件?
您的代码实际上没有任何意义。Select
扩展方法采用Func<T, TResult>
,这意味着返回类型应为IEnumerable<TResult>
,而您将其指定为T
。
在您的问题中,您希望用相同的方法执行Select
和FirstOrDefault
,但这是不可能的,因为结果类型会不同。
Select
:
public static async Task<IEnumerable<TResult>> SelectData<T, TResult>(
string propertyName
)
{
if(string.IsNullOrWhiteSpace(propertyName))
{
return Enumerable.Empty<TResult>();
}
var dataTask = GetTableData<T>();
var tType = Expression.Parameter(typeof(T), "t");
var property = Expression.Property(tType, propertyName);
var selectExpression =
Expression.Lambda<Func<T, TResult>>(property, tType)
.Compile();
return (await dataTask).Select(selectExpression);
}
FirstOrDefault
:
public static async Task<T> FirstOrDefaultData<T>(
string propertyName,
string conditionName,
Func<MemberExpression, MemberExpression, BinaryExpression> comparer
)
{
if(string.IsNullOrWhiteSpace(propertyName) ||
string.IsNullOrWhileSpace(conditionName) ||
comparer == null
{
return default(T);
}
var dataTask = GetTableData<T>();
var tType = Expression.Parameter(typeof(T), "t");
var property = Expression.Property(tType, propertyName);
var condition = Expression.Property(tType, conditionName);
var binaryExpression =
Expression.Lambda<Func<T, bool>>(comparer(property, condition), tType)
.Compile();
return (await dataTask).FirstOrDefault(binaryExpression);
}
用法:
public class Foo
{
public string Bar { get; set; }
public bool Flag { get; set; }
}
var bars = SelectData<Foo, string>("Bar");
var foo = FirstOrDefaultData<Foo>("Bar",
"Flag",
(p, c) => Expression.GreaterThan(p, c));