目标是使用 NHibernate 和 Linq 做这样的事情:
Session.Query<MyClass>().Where(x => x.DateGreaterThen(DateTime.Now))
这个例子稍微简化了一点,但想法是在 Where 谓词中我想调用 MyClass 方法。所以 MyClass 看起来像:
public class MyClass
{
public static readonly Expression<Func<MyClass, DateTime, bool>> GreaterThenExpression =
(x, dt) => x.MyDateTimeProperty > dt.Date;
private static readonly Func<MyClass, DateTime, bool> GreaterThenFunc = GreaterThenExpression.Compile();
public Guid Id { get; set; }
public DateTime MyDateTimeProperty { get; set; }
public bool DateGreaterThen(DateTime dt)
{
return GreaterThenFunc(this, dt);
}
}
自定义生成器:
public class EntityMethodGenerator<T1, T2, TResult> : BaseHqlGeneratorForMethod
{
private Expression<Func<T1, T2, TResult>> _returnValueExpression;
public EntityMethodGenerator()
{
SupportedMethods = new[]
{
ReflectionHelper.GetMethodDefinition<MyClass>(myClass => myClass.DateGreaterThen(DateTime.Now))
};
}
public static void Register(ILinqToHqlGeneratorsRegistry registry, Expression<Action<T1>> method, Expression<Func<T1, T2, TResult>> returnValueExpression)
{
var generator = new EntityMethodGenerator<T1, T2, TResult> { _returnValueExpression = returnValueExpression };
registry.RegisterGenerator(ReflectionHelper.GetMethodDefinition(method), generator);
}
public override HqlTreeNode BuildHql(
MethodInfo method,
Expression targetObject,
ReadOnlyCollection<Expression> arguments,
HqlTreeBuilder treeBuilder,
IHqlExpressionVisitor visitor)
{
return visitor.Visit(_returnValueExpression);
}
}
最后是自定义自定义生成器注册表:
public class OwnLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
public OwnLinqToHqlGeneratorsRegistry()
{
EntityMethodGenerator<MyClass, DateTime, bool>.Register(this, (myClass) => myClass.DateGreaterThen(DateTime.Now), MyClass.GreaterThenExpression);
}
}
但这不起作用,我System.Data.SqlClient.SqlException : Invalid column name 'dt'.
怀疑我的 BuildHql 方法没有正确实现,有什么帮助解决这个问题吗?
顺便说一句,我想在生成器中使用表达式,比如我的而不是在方法GreaterThenExpression
中手动构建 HqlTreeBuildHql