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

本文关键字:属性 抽象 延迟加载 静态 用于 | 更新日期: 2023-09-27 17:57:41

我正在制作一个使用数据库的简短程序。我的大多数表都有一个表示它们的类,通常,我通过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);

这句话简直令人尴尬。

虽然我可能会咬紧牙关在每个类中实现这个方法,但我想知道你们能想出什么很酷的模式。我已经研究了一些,但它们大多需要在派生类中实现。

该算法的关键方面包括:

  • 每个项目只加载一次
  • 加载新项目时填充列表"已加载"
  • 实现被保持在最低限度——在这种情况下,它只是"加载"answers"tableName"(setData已经是必需的)
  • SQLite并不是真正的焦点,它的想法是只执行一次重载

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

编辑:

我可能已经承诺,我希望每个类都有自己的实例静态字典。(抽象静态的原因)

我想,重点是寻找一种在派生类中强制使用静态变量的方法。

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

我不明白为什么所有这些都必须受到保护或抽象。这里有一个简单的例子,我认为,可以达到你的目标。它对继承的类进行反射,以找到基类缓存用于查找的静态"TableName"属性。另一种选择是在继承的类上使用属性,但无论哪种方式都需要反射。如果未定义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);
    }
}