3

使用 FluentNHibernate、新的 QueryOver API 和新的 Linq 提供程序的众多原因之一都是因为它们消除了“魔术字符串”或表示属性的字符串或其他可以在编译时表示的东西。

遗憾的是,我正在使用尚未升级为支持 QueryOver 或 LINQ 的 NHibernate 的空间扩展。结果,我不得不使用 QueryOver Lambda 表达式和字符串的组合来表示我想要查询的属性等。

我想做的是——我想要一种方法来询问 Fluent NHibernate(或者可能是 NHibernate QueryOver API)魔术字符串“应该是”什么。这是一个伪代码示例:

目前,我会写——

var x = session.QueryOver<Shuttle>().Add(SpatialRestrictions.Intersects("abc", other_object));

我想写的是——

var x = session.QueryOver<Shuttle>().Add(SpatialRestriction.Intersects(session.GetMagicString<Shuttle>(x => x.Abc), other_object));

有这样的东西吗?会不会很难写?

编辑:我只是想指出,这不仅仅适用于空间——实际上任何尚未转换为 QueryOver 或 LINQ 的东西都可能受益。

4

2 回答 2

4

更新

C# 6 中的nameof运算符为此提供了编译时支持。


有一个更简单的解决方案 - 表达式。

举个例子:

public static class ExpressionsExtractor
{
    public static string GetMemberName<TObj, TProp>(Expression<Func<TObj, TProp>> expression)
    {
        var memberExpression = expression.Body as MemberExpression;

        if (memberExpression == null)
            return null;

        return memberExpression.Member.Name;
    }
}

以及用法:

var propName = ExpressionsExtractor.GetMemberName<Person, int>(p => p.Id);

ExpressionsExtractor 只是一个建议,您可以将此方法包装在您想要的任何类中,可能作为扩展方法或最好是非静态类。

您的示例可能看起来像这样:

var abcPropertyName = ExpressionsExtractor.GetMemberName<Shuttle, IGeometry>(x => x.Abc);
var x = session.QueryOver<Shuttle>().Add(SpatialRestriction.Intersects(abcPropertyName, other_object));
于 2010-09-01T20:23:38.537 回答
0

假设我理解您的问题,您可能想要的是每个实体的帮助器类,包括列名、属性名和其他有用的东西,特别是如果您想使用 ICriteria 搜索。http://nhforge.org/wikis/general/open-source-project-ecosystem.aspx有很多项目可能会有所帮助。NhGen ( http://sourceforge.net/projects/nhgen/ ) 创建了非常简单的帮助类,它可以帮助你找到你想要的设计路径。

澄清编辑:遵循“我不明白”的评论

简而言之,我不相信现在有适合您的解决方案。QueryOver 项目并没有达到你想要的程度。因此,同时作为一种可能的解决方案,要删除魔术字符串,请构建一个帮助程序类,因此您的查询变为

var x = session.QueryOver<Shuttle>().Add(SpatialRestrictions.Intersects(ShuttleHelper.Abc, other_object));

这样你的魔法字符串就在其他属性的后面(我只是选择 .Abc 来演示,但我相信你会对你想要的有更好的了解)然后如果“abc”发生变化(比如“xyz”)你要么将属性名称从 .Abc 更改为 .Xyz,然后您将遇到构建错误,以显示您需要更新代码的位置(就像您使用 lambda 表达式一样)或者只是将 .Abc 属性的值更改为“xyz” - 只有当您的属性具有一些有意义的名称(例如 .OtherObjectIntersectingColumn 等)而不是该属性名称本身时,这才会真正起作用。这确实具有不必更新代码来纠正构建错误的优点。那时您的查询可能是

var x = session.QueryOver<Shuttle>().Add(SpatialRestrictions.Intersects(ShuttleHelper.OtherObjectIntersectingColumn, other_object));

我提到了开源项目生态系统页面,因为它可以为您提供一些关于其他人制作了哪些类型的帮助类的指示,这样您就不必重新发明轮子了。

于 2010-07-29T21:45:04.440 回答