2013-01-16 35 views
4

我從Lambda表達式鑄造

Expression<Func<T, bool>> predicate 

如何能轉換爲

Expression<Func<SomeType, bool>> predicate 

到目前爲止找不到方法。或者至少通過使用謂詞的第一個字符串表示來創建一個新的Expression<Func<SomeType, bool>>

如果有幫助,T僅限於實現ISomeInterface的類型,並且SomeType實現它。

LE:進一步澄清

的接口是一樣的東西:

public interface ICacheable 
{ 
    List<T> GetObjects<T>(Expression<Func<T, bool>> predicate) where T : ICacheable; 
} 

,那麼你必須

public partial class Video : ICacheable 
{ 
    public List<T> GetObjects<T>(Expression<Func<T, bool>> predicate) where T : ICacheable 
    { 
     // implementation here that returns the actual List<Video> 
     // but when I try to query the dbcontext I can't pass a predicate with type T, I have to cast it somehow 
     List<Video> videos = db.Videos.Where(predicate).ToList(); // not working 
    } 
} 

,那麼你必須:

public class RedisCache 
{ 
    public List<T> GetList<T>(Expression<Func<T, bool>> predicate) where T : ICacheable 
    { 
     List<T> objList = // get objects from cache store here 
     if(objList == null) 
     { 
      List<T> objList = GetObjects<T>(predicate); 
      // cache the result next 
     } 
     return objList; 
    } 
} 

我用上面的任何類,像這樣:

// If the list is not found, the cache store automatically retrieves 
// and caches the data based on the methods enforced by the interface 
// The overall structure and logic has more to it. 
List<Video> videos = redisCache.GetList<Video>(v => v.Title.Contains("some text")); 
List<Image> images = redisCache.GetList<Image>(v => v.Title.Contains("another text")); 

我將擴大這對任何類型的對象我需要超高速緩存,與方法,將允許緩存存儲自動檢索一個實體或列表如果它們沒有在緩存中找到,則爲實體。但我可能會完全錯誤。

+6

那麼你會想到,如果它獲得通過ISomeInterface'的'實現這*不*'SomeType'發生? –

+0

關於第二個想法,我不確定這是否是一個騙局,但是無論如何,你可能想要閱讀這個問題。如果你需要做更多的事情而不是愚蠢的類型替代,我的哀悼。 – Jon

+0

@Jon它確實是一個確切的重複。 – usr

回答

1

我沒有達到我的實體框架劃傷,但我知道,內LINQ的DatabaseContextGetTable<T>返回基於通用的表格。如果「GetTable equivalent for ObjectContext」有什麼值得注意的地方,它也可以在EF中使用?

爲了使您的發言真正通用的,你可以試試這個:

public MyBaseObject<T> 
{ 
    public List<T> GetObjects<T>(Expression<Func<T, bool>> predicate) where T : ICacheable 
    { 
     return db.CreateObjectSet<T>().Where(predicate).ToList(); 
    } 
} 

public partial class Image : MyBaseObject<Image>, ICacheable 
{ 
} 

public partial class Video : MyBaseObject<Video>, ICacheable 
{ 
} 
1

這裏是(非常)基本的東西,我希望可以幫助你使用泛型進行緩存。

// ICacheable interface is used as a flag for cacheable classes 
public interface ICacheable 
{ 
} 

// Videos and Images are ICacheable 
public class Video : ICacheable 
{ 
    public String Title { get; set; } 
} 

public class Image : ICacheable 
{ 
    public String Title { get; set; } 
} 

// CacheStore will keep all objects loaded for a class, 
// as well as the hashcodes of the predicates used to load these objects 
public class CacheStore<T> where T : ICacheable 
{ 
    static List<T> loadedObjects = new List<T>(); 
    static List<int> loadedPredicatesHashCodes = new List<int>(); 

    public static List<T> GetObjects(Expression<Func<T, bool>> predicate) 
    { 

     if (loadedPredicatesHashCodes.Contains(predicate.GetHashCode<T>())) 
      // objects corresponding to this predicate are in the cache, filter all cached objects with predicate 
      return loadedObjects.Where(predicate.Compile()).ToList(); 
     else 
      return null; 
    } 

    // Store objects in the cache, as well as the predicates used to load them  
    public static void StoreObjects(List<T> objects, Expression<Func<T, bool>> predicate) 
    { 
     var hashCode = predicate.GetHashCode<T>(); 
     if (!loadedPredicatesHashCodes.Contains(hashCode)) 
     { 
      loadedPredicatesHashCodes.Add(hashCode); 
      loadedObjects = loadedObjects.Union(objects).ToList(); 
     } 
    } 
} 

// DbLoader for objets of a given class 
public class DbStore<T> where T : ICacheable 
{ 
    public static List<T> GetDbObjects(Expression<Func<T, bool>> predicate) 
    { 
     return new List<T>(); // in real life, load objects from Db, with predicate 
    } 
} 

// your redis cache 
public class RedisCache 
{ 
    public static List<T> GetList<T>(Expression<Func<T, bool>> predicate) where T:ICacheable 
    { 
     // try to load from cache 
     var objList = CacheStore<T>.GetObjects(predicate); 
     if(objList == null) 
     { 
      // cache does not contains objects, load from db 
      objList = DbStore<T>.GetDbObjects(predicate); 
      // store in cache 
      CacheStore<T>.StoreObjects(objList,predicate); 
     } 
     return objList; 
    } 
} 

// example of using cache 
public class useRedisCache 
{ 
    List<Video> videos = RedisCache.GetList<Video>(v => v.Title.Contains("some text")); 
    List<Image> images = RedisCache.GetList<Image>(i => i.Title.Contains("another text")); 
} 

// utility for serializing a predicate and get a hashcode (might be useless, depending on .Equals result on two equivalent predicates) 
public static class PredicateSerializer 
{ 
    public static int GetHashCode<T>(this Expression<Func<T, bool>> predicate) where T : ICacheable 
    { 
     var serializer = new XmlSerializer(typeof(Expression<Func<T, bool>>)); 
     var strw = new StringWriter(); 
     var sw = XmlWriter.Create(strw); 
     serializer.Serialize(sw, predicate); 
     sw.Close(); 
     return strw.ToString().GetHashCode(); 
    } 
}