替代静态抽象属性的延迟加载

时间:2014-04-09 17:36:28

标签: c# static lazy-loading abstract

我正在制作一个使用数据库的短程序。我的大多数表都有一个代表它们的类,通常我会通过Id访问此表中的行。所以我觉得我很漂亮并为我的课程创建了这个基础类,认为我能够标准化我的方法。我做了这个:

public abstract class Loadable<T> where T: Loadable<T>, new()
{
    protected abstract static List<T> loaded { get; set;}
    protected abstract static string tableName { get; set; }
    protected abstract void setData(DataRow data);
    public abstract int id { get; set; }
    public static T getById(int id)
    {
        if (loaded.Any((g) => g.id == id))
            return (T)loaded.First((g) => g.id == id);

        T ret = new T();
        ret.setData(SQLiteDB.main.getRowById(tableName, id));
        T.
        return ret;
    }
}

当我完成时,我尝试用一​​种自鸣得意的满足感进行编译,以便了解抽象静态不是一种东西。标准菜鸟错误。 <更详细>

T.loaded.Add(ret);

线条只是简单的尴尬。

虽然我可能会在每个班级中找到灵感并实施这种方法,但我想知道你们可以提出什么样的酷炫模式。我已经研究了一些,但它们大多需要在派生类中实现。

算法的关键方面包括:

  • 每件物品仅加载一次。
  • 列出&#34;已加载&#34;在加载新项目时填充
  • 将实施工作保持在最低限度 - 在这种情况下,它只是&#34;已加载&#34;和&#34; tableName&#34;(已经需要setData)。
  • SQLite并不是真正的焦点,我的想法是只执行一次重载。

这可能,还是只是一个白日梦?

修改:

我可能已经遗漏了我希望每个Class都有自己的静态实例字典。(抽象静态的原因)

我想,整个观点是寻找一种在派生类中强制执行静态变量的方法。

1 个答案:

答案 0 :(得分:1)

我不明白为什么所有这些都必须受到保护或抽象。这是一个简单的例子,我认为,它实现了你的目标。它对继承的类进行反射,以找到静态的&#34; TableName&#34;基类缓存查找的属性。另一种选择是在继承的类上使用属性,但无论哪种方式都需要反射。如果未定义TableName,则抛出异常。此外,我使用ConcurrentDictionary来更快,更安全地查找实例。

public abstract class Loadable<T> where T: Loadable<T>, new()
{
    private readonly static ConcurrentDictionary<int, T> _cache = new ConcurrentDictionary<int, T>();

    private readonly static Func<int, T> _addDelegate = key => {
        T item = new T();
        item.SetData(SQLiteDB.main.getRowById(_tableName, key));
        return item;
    };

    private static readonly string _tableName;

    static Loadable()
    {
        var prop = typeof(T).GetProperty("TableName", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public);
        if (prop == null)
            throw new NotSupportedException(string.Format("Type '{0}' does not support TableName", typeof(T)));

        _tableName = (string)prop.GetValue(null);
    }

    protected abstract void SetData(DataRow data);

    public virtual int Id { get; set; }

    public static T GetById(int id)
    {
        return _cache.GetOrAdd(id, _addDelegate);
    }
}