[英]How to check if a static constructor has been called?
我有一些類來緩存數據庫中的數據,這些類在調用靜態構造函數時會加載數據。
我需要在所有這些類中調用靜態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。
乍一看,我認為這可能是一個問題,其中<grin>
量子力學哥本哈根解釋可能適用(“一看到它,它就會改變 ”)。 </grin>
即你在課堂上做的任何事情,以觀察它是否已被初始化可能會導致它自己初始化......
但是您不必在類中執行此操作,只需在其他位置(除了這些靜態類之外)保留一個列表,該列表在初始化時由每個靜態類填充。 然后在你的重置函數中,只需遍歷列表中的類。
如果您有幾個這樣的類,那么如何通過工廠或經理類來控制它們的實例化。 這可以跟蹤已使用的內容並在適當時調用重新加載方法。
您不應該在靜態構造函數中使用長時間運行的操作,或者至少它們不應該同步運行。 靜態構造函數隱式運行,當隱式執行占用大量時間時,它會產生有趣的錯誤:)
此外,如果您確實使用靜態構造函數,方法以及維護狀態的東西,請嘗試在完全靜態的類中隔離它們,因此在大多數情況下,它們將像單例一樣運行。 我會將實現更改為以下內容:
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
我問是否有任何方法可以查看是否調用了靜態構造函數。 我認為答案是否定的,但解決方法是創建一個可以跟蹤存儲庫的管理器。 目標是盡可能少地改變現有的類。
我對經理類的解決方案是:
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。
您可以使用單例模式,並添加一個字段,告訴您是否已創建唯一實例
實際上不需要創建單例,只需保留靜態類,並在調用應該返回它的屬性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
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.