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

私は Entity Framework をスクラッチするつもりはありませんが、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 に答える
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 に答える