4

我怎样才能从

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

我会将其扩展到我需要可缓存的任何类型的对象,如果在缓存中找不到实体或实体列表,则允许缓存存储自动检索实体或实体列表的方法。不过,我可能做错了。

4

2 回答 2

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();
    }
}
于 2013-01-17T17:18:23.383 回答
1

我对我的实体框架不了解,但我知道DatabaseContextLINQ 内部有一个GetTable<T>基于泛型返回表的方法。如果“ ObjectContext 的 GetTable 等效项”可以通过,它是否也可以在 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
{
}
于 2013-01-17T17:29:41.777 回答