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

C# 使用String.IsNullOrEmpty(String)和Nhibernate创建动态Linq表达式,c#,.net,linq,generics,nhibernate,C#,.net,Linq,Generics,Nhibernate,我正在尝试使用表达式创建一个动态nhibernate查询。我对Contains、StartsWith和EndsWith这样的函数没有问题,但我似乎无法让它与IsNullOrEmpty一起工作。以下是一些上下文: 包含: MethodInfo contains = typeof(string).GetMethod("Contains", new Type[] { typeof(string) }); ParameterExpression param = Expression.Parameter(

我正在尝试使用表达式创建一个动态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);
当我在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));  
有人知道这是为什么/如何解决吗

编辑:

我为什么要这样做:

在我的web层中,我向用户显示了这个x.MyStringProperty数据。它们能够根据这个属性进行过滤,我希望能够通过这些字符串方法过滤数据。web层只需将这些函数传回:

BeginsWith
EndsWith
Contains
IsNullOrEmpty
NotIsNullOrEmpty
从这些名称中,我可以使用上面的代码直接将它们转换为string方法。因此,我可以传递web层中的任何类型,并能够过滤任何字符串属性。这是非常强大的,因为对于我的数百个类,我可以有一个方法来处理每个类的过滤。如前所述,它与非静态方法一起工作,因为构建的表达式是:

x -> x.MyStringProperty.NonStaticMethod("SomeFilterValue");
在Expression.Call的文档中有这样的说明,您也应该能够使用静态方法来实现这一点。由于它适用于非静态方法,因此必须有一种方法来执行IsNullOrEmpty,从而使表达式

x -> string.StaticMethod(x.MyStringProperty)
我敢打赌,如果我创建表达式,它会起作用

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

但是这是一个解决办法,作为一个程序员,我觉得我需要找出如何使用静态方法来完成上面的工作

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

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

public interface IHqlGeneratorForMethod
{
    IEnumerable<MethodInfo> SupportedMethods { get; }
    HqlTreeNode BuildHql(MethodInfo method, Expression targetObject
          , ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder
          , IHqlExpressionVisitor visitor);
}
如您所见,
Contains
EndsWith
StartsWith
有责任。但是在那里找不到IsNullOrEmpty

换句话说,无论您在全局环境中做什么,您的IsNullOrEmpty都应该以如下语句结束:

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

非常感谢你的答复。我对以上内容进行了编辑,以便为您提供更多信息。你上面的解决方案可能会奏效,我会很快检查出来,但也许你在编辑中也有这个问题的答案。事实上,我使用了非常相似的逻辑。我的意思是,在服务器上绑定
过滤器
对象,然后将其转换为限制(criteriaapi)。我想说的是,它也可以以类似的方式应用到你的案例中。它是如何工作的?我没有构建表达式,而是通过了一些扩展方法的标准。如果其中任何一个能够正确读取筛选器,则会附加限制。限制对字符串有很强的支持,所以如果我对过滤器绑定应用了足够的验证,我可以使用字符串。也许这会有所帮助,但这并不是相对于静态方法而言表达式生成器的答案;)我们从Criteria切换到Linq,再切换到nhibernate,因此表达式是必要的。我来看看==null | |“”解决方案是否有效。我会把结果发回来,如果成功的话,我会给你答案。再次感谢您是的,似乎可以使用==null和==“”。非常感谢你的帮助!
DictionaryItemGenerator
DictionaryContainsKeyGenerator
EqualsGenerator
BoolEqualsGenerator
MathGenerator
AnyHqlGenerator
AllHqlGenerator
MinHqlGenerator
MaxHqlGenerator
CollectionContainsGenerator
HqlGeneratorForExtensionMethod
StartsWithGenerator // StartsWith
EndsWithGenerator   // EndsWith
ContainsGenerator   // Contains
ToLowerGenerator
ToUpperGenerator
SubStringGenerator
IndexOfGenerator
ReplaceGenerator
TrimGenerator
.Where(x => x.MyProperty == null || x.MyProperty == "")