【问题标题】:How to pass a user-input string as a field name to access a field within an object?如何将用户输入字符串作为字段名称传递以访问对象内的字段?
【发布时间】:2014-06-27 08:27:50
【问题描述】:
我正在使用 linq 从数据库中进行一些搜索。我有多个列名,例如国家、姓名、电话号码...
现在我创建了一个下拉列表并将用户选择的数据作为参数“searchedField”传递给我的控制器方法。现在,如果我输入“国家”,我希望代码是
entries = entries.Where(s => s.country.Contains(searchString));
如果用户选择了“姓名”
entries = entries.Where(s => s.name.Contains(searchString));
请原谅这个相当不合理的例子,因为我总是可以只复制行并制作案例,但我想知道是否有一种方法可以利用反射之类的东西将字符串转换为“代码”来访问字段?
String searchedField = "name"
...
entries = entries.Where(s => s.searchedField.Contains(searchString));
这是我的第一个问题,谢谢!
【问题讨论】:
标签:
c#
linq
system.reflection
【解决方案1】:
您可以使用Dynamic Linq。
entries = entries
.Where(
string.Format(
"{0} = '{1}'",
searchedField,
searchString
)
);
注意:取决于字段的类型,您是否需要添加引号。
【解决方案2】:
您可以进行反射查找(注意:我省略了错误检查):
string GetPropertyAsString(object obj, string propertyName)
{
var propertyInfo - obj.GetType().GetProperty(propertyName);
return propertyInfo.GetValue(obj).ToString();
}
然后说
entries = entries.Where(s => GetPropertyAsString(s, searchedField).Contains(searchString));
【解决方案3】:
您可以为此构建一个表达式树(它将与 Linq to 实体一起使用)。
public static class QueryableExtensions {
public static IQueryable<T> Filter<T>(this IQueryable<T> queryable, string propertyName, string searchValue)
{
var type = typeof (T);
//this will be the left part of the lambda
var parameter = Expression.Parameter(type, "s");
//s.country for example
var property = Expression.Property(parameter, propertyName);
//string.Contains method
var containsMethod = typeof (string).GetMethod("Contains", new[] {typeof (string)});
//s.country.Contains(<yoursearchvalue>)
var expression = Expression.Call(property, containsMethod, Expression.Constant(searchValue));
//s => s.country.Contains(<yoursearchvalue>)
var lambda = Expression.Lambda<Func<T, bool>>(expression, parameter);
//filter your queryable with predicate
return queryable.Where(lambda);
}
}
用法
var fieldtosearch = "country";
entries = entries.Filter(fieldtosearch , searchString);
【解决方案4】:
一般来说,除了使用动态 linq 查询之外,您还可以使用 Expression 构建一个通用方法来构造一个属性 Getter 并在您的 linq 查询中使用它,这是一个快速示例:
public static Func<TObject, TProperty> GetPropGetter<TObject, TProperty>(string propertyName)
{
ParameterExpression paramExpression = Expression.Parameter(typeof(TObject), "value");
Expression propertyGetterExpression = Expression.Property(paramExpression, propertyName);
Func<TObject, TProperty> result =
Expression.Lambda<Func<TObject, TProperty>>(propertyGetterExpression, paramExpression).Compile();
return result;
}
使用它:
var getter = GetPropGetter<YourEntity, string>("Name");
var found = entites.Where(m => getter(m).Contains("someInput"));