我有一些类来缓存数据库中的数据,这些类在调用静态构造函数时会加载数据。
我需要在所有这些类中调用静态Reload方法,除了那些尚未初始化的类。
例如:City缓存数据库中的数据
public class City
{
public City Get(string key)
{
City city;
FCities.TryGetValue(key, out city);
return city;
}
private static Dictionary<string, City> FCities;
static City()
{
LoadAllCitiesFromDatabase();
}
public static void Reload()
{
LoadAllCitiesFromDatabase();
}
private static void LoadAllCitiesFromDatabase()
{
// Reading all citynames from database (a very slow operation)
Dictionary<string, City> loadedCities = new Dictionary<string, City>();
...
FCities = loadedCities;
}
}
问题是City可能尚未使用(可能未在此服务中使用),因此没有理由从数据库加载它。
我重新加载所有方法看起来很像这样:
public static class ReloadAll
{
public static void Do()
{
foreach (Type classType in AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Where(t => t.IsClass && !t.IsAbstract))
{
MethodInfo staticReload = classType.GetMethods().FirstOrDefault(m => m.IsStatic && m.IsPublic && m.ReturnType == typeof(void) && m.Name == "Reload" && m.GetParameters().Length == 0);
if (staticReload != null)
{
if (StaticConstructorHasBeenCalled(classType))
staticReload.Invoke(null, null);
}
}
}
private bool StaticConstructorHasBeenCalled(Type classType)
{
// How do I check if static constructor has been called?
return true;
}
}
我需要一点帮助来实现StaticConstructorHasBeenCalled。
答案 0 :(得分:7)
乍一看,我认为这可能是<grin>
量子力学哥本哈根解释可能适用的问题(“一看到它就会改变 EM>“)。 </grin>
I.e.你在课堂上做的任何事情,以观察它是否已被初始化可能会 导致 它初始化自己......
但是你不必在类中执行它,只需在其他地方(除了这些静态类之外)保留一个列表,该列表在初始化时由每个静态类填充。然后在你的重置函数中,只需遍历列表中的类。
答案 1 :(得分:2)
如果你有几个这样的类,那么如何通过工厂或经理类来控制它们的实例化。 这可以跟踪已使用的内容,并在适当的时候调用重新加载方法。
答案 2 :(得分:1)
您不应该在静态构造函数中使用长时间运行的操作,或者至少它们不应该同步运行。静态构造函数隐式运行,当隐式执行需要很长时间时,它会产生有趣的错误:)
另外,如果你使用静态构造函数,方法和诸如维护状态的东西,尝试在完全静态的类中隔离它们,因此在大多数情况下它们将像单例一样运行。我会将实现更改为以下内容:
public static class CityRepository
{
private static bool areCitiesLoaded;
private List<City> cities;
static CityRepository()
{
areCitiesLoaded = false;
cities = new List<City>();
}
//method that will be called in all other method, to ensure
//that the cities are loaded
private static void EnsureLoad()
{
if (!areCitiesLoaded)
{
LoadAllCitiesFromDatabase();
areCitiesLoaded = true;
}
}
}
public class City {} //city instance methods
答案 3 :(得分:1)
我问是否有办法查看是否调用了静态构造函数。我认为答案是否定的,但解决方法是创建一个可以跟踪存储库的管理器。 目标是尽可能少地改变现有的类。
我对经理类的解决方案是:
public static class RepositoryManager
{
public delegate void Reload();
private static List<Reload> FRepositories = new List<Reload>();
public static void Register(Reload repository)
{
lock (FRepositories)
{
FRepositories.Add(repository);
}
repository();
}
public static void ReloadAll()
{
List<Reload> list;
lock (FRepositories)
{
list = new List<Reload>(FRepositories);
}
foreach (Reload repository in list)
repository();
}
}
使用City类的示例,更改将仅限于静态构造函数。
public class City
{
// ...
static City()
{
RepositoryManager.Register(LoadAllCitiesFromDatabase);
}
// ...
}
我的ReloadAll方法就像下面这样简单:
public void ReloadAll()
{
RepositoryManager.ReloadAll();
}
感谢您的所有答案,我已经奖励了每个人,他们建议某种经理作为解决问题的方法。
这个解决方案的缺点是,每当有人创建需要重新加载/更新/清除一次的存储库时,他们必须记住使用RepositoryManager。
答案 4 :(得分:0)
您可以使用单例模式,并添加一个字段,告诉您是否已创建唯一实例
实际上不需要创建单例,只需保留静态类,并在调用应该返回它的属性getter时加载数据:
static class City
{
static bool _loaded = false;
public bool Loaded { get { return _loaded; } }
public static List<C> Data
{
get
{
if (!_loaded)
{
doLoading();
_loaded = true
}
}
}
}