我想标题说明了我在寻找什么。这是我正在努力实现的一个例子。
我有实体(其中一些在运行时使用 CodeDom 生成)
public abstract class Content
{
public virtual Page Parent { get; set; }
public virtual ISet<Property> Properties { get; set; }
// T GetPropertyValue<T>(string)
// SetPropertyValue(string, object)
}
public abstract class Page : Content
{
public virtual string Path { get; set; }
}
// Generated with CodeDom
public class Post : Page
{
public virtual string Text
{
get
{
// get value from Properties
return GetPropertyValue<string>("Text");
}
set
{
// set value to Properties
SetPropertyValue("Text", value);
}
}
}
我正在使用 NHibernate 来查询项目。
问题:我不能Post.Text
在 Where 子句中使用。
解决方案:创建自己的扩展方法,将 lambda 表达式转换为另一种格式。
例如查询
var posts = session.Query<Post>().Filter(p =>
p.Parent.Path.StartsWith("/blogs/programming/") &&
p.Text.Contains("hello"));
可以转换为以下任一
public static IQueryable<T> Filter<T>(this IQueryable<T> query, Expression<Func<T, bool>> filterExpr)
{
return query.Where(p =>
p.Parent.Path.StartsWith("/blogs/programming/") &&
p.Properties.OfType<StringProperty>().Any(p2 =>
p2.Name == "Text" &&
p2.StringValue.Contains("hello")));
}
public static IQueryable<T> Filter<T>(this IQueryable<T> query, Expression<Func<T, bool>> filterExpr)
{
var ids1 = session.Query<Content>().Where(p =>
p.Parent.Path.StartsWith("/blogs/programming/"))
.Select(p => p.Id);
var ids2 = session.Query<StringProperty>().Where(p =>
p.Name == "Text" &&
p.StringValue.Contains("hello"))
.Select(p => p.Content.Id);
var ids = ids1.Intersect(ids2);
return query.Where(p => ids.Contains(p.Id));
}
有什么好的不平凡的例子或开源项目?