我们如何查询通用columnName?

时间:2012-11-05 14:56:31

标签: vb.net generics lambda

到目前为止,我们有一个搜索tenantName列的方法(OnSearchButtonClick):

Private Sub OnSearchButtonClick(ByVal searchValue As String)
            _filteredTenants = New ListCollectionView(_allTenants.Cast(Of TenantOverviewDto).Where(Function(p) p.TenantName.ToUpper().StartsWith(searchValue.ToUpper())).ToList())
 End Sub

在此方法中,我们希望将另一个字符串作为参数传递,其中包含TenantOverviewDto的某个列的名称。 例如,如果我们想要在名为“Runners”的组中查找一个tennant,我们希望在searchValue参数中传递“Runners”并在new参数中分组,然后执行查看group列的查询。 (如果第二个参数是TenantName,我们应该查看TenantName列)

有没有人知道我们如何才能做到这一点?非常感谢所有帮助。

3 个答案:

答案 0 :(得分:1)

我的同事找到了一个反思的解决方案。 方法如下所示:

Private Sub OnSearchButtonClick(ByVal searchValue As String, ByVal columnName As String)

            _filteredTenants = New ListCollectionView(_allTenants.Cast(Of TenantOverviewDto).Where(Function(p) GetPropertyValue(p, columnName).ToUpper().StartsWith(searchValue.ToUpper())).ToList())
End Sub

在GetPropertyValue方法中,我们将使用反射:

 Private Function GetPropertyValue(ByVal o As Object, ByVal propertyName As String) As Object

            Dim type As Type = o.GetType()
            Dim info As PropertyInfo = type.GetProperty(propertyName)
            Dim value As Object = info.GetValue(o, Nothing)
            Return value

        End Function

首先我们得到我们传递的对象类型(在本例中为TenantOverviewDto)。其次,我们得到了我们传递的columnName的propertyInfo。然后我们得到相应的值,然后我们发回这个值。

答案 1 :(得分:0)

在这种情况下,反射解决方案更简单,更简洁,因此我更喜欢使用它。

但是,我认为使用动态表达式发布C#解决方案很有意思:

private void OnSearchButtonClick(string propertyName, string searchValue)
{
    var parameter = Expression.Parameter(typeof(TenantOverviewDto), "p");

    var toUpperMethodInfo = typeof(string).GetMethods()
        .Single(m => m.Name == "ToUpper" && !m.GetParameters().Any());

    var startsWithMethodInfo = typeof(string).GetMethods()
        .Single(m => m.Name == "StartsWith" && m.GetParameters().Count() == 1);

    var expression =
        Expression.Call(
            Expression.Call(
                Expression.Property(parameter, propertyName), 
                toUpperMethodInfo),
            startsWithMethodInfo,
            Expression.Constant(searchValue.ToUpper())
        );

    var compiledCondition = Expression.Lambda<Func<TenantOverviewDto, bool>>
        (expression, parameter).Compile();

    _filteredTenants = new ListCollectionView(
        _allTenants.Cast<TenantOverviewDto>().Where(compiledCondition).ToList());
}

这种方法过于复杂,无法满足本案例的需要。但是,当条件比将变量属性与常量字符串进行比较时更复杂,它可能会派上用场。

答案 2 :(得分:0)

尝试此解决方案:

Private Sub OnSearchButtonClick(ByVal searchValue As String, ByVal columnName As String)
    _filteredTenants = _filteredTenants.findAll(f=>f[columnName].toString().StartsWith(searchValue.ToUpper())).toList()
End Sub