2012-05-30 53 views
0

我想標題說明了我在找什麼。這是我想要實現的一個例子。遍歷/轉換表達樹的好例子

我有實體(其中一些在運行時生成與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的查詢項目。
問題:我不能在Where子句中使用Post.Text
解決方案:創建自己的擴展方法,將lambda表達式轉換爲另一種格式。

E.g查詢

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)); 
} 

任何好的非簡單的例子或開源項目?

回答

0

也許你可以看看Brahma,我的LINQ to OpenCL翻譯器。 http://brahma.codeolex.com

它做了一件我非常類似於你想要達到的東西。

希望這會有所幫助!