gpt4 book ai didi

c# - 使用 String.IsNullOrEmpty(string) 和 Nhibernate 创建动态 Linq 表达式

转载 作者:行者123 更新时间:2023-11-30 22:09:46 24 4
gpt4 key购买 nike

我正在尝试使用表达式创建动态 nhibernate 查询。我对 Contains、StartsWith 和 EndsWith 等函数没有问题,但我似乎无法让它与 IsNullOrEmpty 一起使用。这是一些上下文:

包含:

MethodInfo contains = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
ParameterExpression param = Expression.Parameter(typeof(MyType), "x");
Expression expression = null;
PropertyInfo info = typeof(MyType).Property("MyStringProperty");
expression = Expression.Property(param, info);

expression = Expression.Call(expression, info, Expression.Constant("Does it contain this string", typeof(string)));

在所有这一切的最后,表达式在调试器中是这样的:

expression = { x.MyStringProperty };  

然后我把它变成一个 lambda 表达式:

var finalExpression = Expression.Lambda<Func<MyType, bool>>(expression, param);

最后,finalExpression 是这样的:

x => x.MyStringProperty.Contains("Does it contain this string");  

当我通过 nhibernate 运行它时,它完全按照我的要求运行。不过,有了 IsNullOrEmpty,这就是我所拥有的:

MethodInfo isNull = typeof(string).GetMethod("IsNullOrEmpty", new Type[] { typeof(string) } );
ParameterExpression param = Expression.Parameter(typeof(MyType), "x");
PropertyInfo info = typeof(MyType).GetProperty("MyStringProperty");
expression = Expression.Property(param, info);
expression = Expression.Call(isNull, expression);

最后,表达式等于:

expression = { IsNullOrEmpty(x.MyStringProperty) }

在 lambda 转换之后它变成:

finalExpression = { x => IsNullOrEmpty(x) }

这看起来完全像它应该的那样(虽然我承认它可能应该读作 string.IsNullOrEmpty(x)),但是当我通过 nhibernate 运行它时,我得到错误:

NotSupportedException
Message: Boolean IsNullOrEmpty(System.String)

有人知道这是为什么吗?如果我运行一个非动态查询并像这样手写一个 where 子句,它可以正常工作:

nhibernateDataProvider.Where(x => string.IsNullOrEmpty(x.MySTringProperty));  

有人知道这是为什么/如何解决这个问题?

编辑:

我为什么要这样做:

在我的网络层中,我向用户显示了这个 x.MyStringProperty 数据。他们有能力通过这个属性进行过滤,而我希望能够通过这些字符串方法来过滤数据。 Web 层只是将这些函数传回:

BeginsWith
EndsWith
Contains
IsNullOrEmpty
NotIsNullOrEmpty

根据这些名称,我可以使用上述代码直接将它们转换为字符串方法。因此,我可以传递 Web 层中的任何类型,并能够过滤任何字符串属性。这是非常强大的,因为对于我所有的数百个类,我可以有一个方法来处理每个类的过滤。正如我之前所说,IT 使用非静态方法,因为构建的表达式是:

x -> x.MyStringProperty.NonStaticMethod("SomeFilterValue");

在 Expression.Call 的文档中说得对,您也应该能够使用静态方法来执行此操作。由于它适用于非静态方法,因此必须有一种方法来执行 IsNullOrEmpty,使表达式变为

x -> string.StaticMethod(x.MyStringProperty)

我敢打赌,如果我创建表达式,它会起作用

x -> x.MySTringProperty == null || x.MySTringProperty == ""

但这是一种解决方法,作为一名程序员,我觉得不符合原则,我需要找出如何使用静态方法执行上述操作。

最佳答案

我只是不确定您要在这里实现什么。 动态表达式查询语言 已经存在:它是内置的 LINQ 提供程序。但是,让我们尝试为您提供有关其实现的更多信息。

当内置的 Linq 提供程序接收到由表达式树表示的查询时,将使用访问者模式将其转换为 SQL(中间有一个 HQL 步骤)。一个强大的部分是由接口(interface) IHqlGeneratorForMethod

表示的方法检查
public interface IHqlGeneratorForMethod
{
IEnumerable<MethodInfo> SupportedMethods { get; }
HqlTreeNode BuildHql(MethodInfo method, Expression targetObject
, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder
, IHqlExpressionVisitor visitor);
}

这里的重要部分是一组实现者:

DictionaryItemGenerator
DictionaryContainsKeyGenerator
EqualsGenerator
BoolEqualsGenerator
MathGenerator
AnyHqlGenerator
AllHqlGenerator
MinHqlGenerator
MaxHqlGenerator
CollectionContainsGenerator
HqlGeneratorForExtensionMethod
StartsWithGenerator // StartsWith
EndsWithGenerator // EndsWith
ContainsGenerator // Contains
ToLowerGenerator
ToUpperGenerator
SubStringGenerator
IndexOfGenerator
ReplaceGenerator
TrimGenerator

如您所见,负责ContainsEndsWithStartsWith。但是在那里找不到IsNullOrEmpty

换句话说,无论您在全局中做什么,您的 IsNullOrEmpty 都应该以这样的语句结尾:

.Where(x => x.MyProperty == null || x.MyProperty == "")

关于c# - 使用 String.IsNullOrEmpty(string) 和 Nhibernate 创建动态 Linq 表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21340642/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com