用于延迟加载的静态抽象属性的替代项
本文关键字:属性 抽象 延迟加载 静态 用于 | 更新日期: 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);
}
}