2013-06-01 21 views
0

在我的應用程序中,有一組數據提供者和Redis緩存。 每個執行不同的供應商使用,但他們都儲存自己的數據在Redis的:沒有實例創建的自我註冊類

hset ProviderOne Data "..." 
hset ProviderTwo Data "..." 

我想有一個方法,將刪除數據中存在的所有代碼提供商。

del ProviderOne 
del ProviderTwo 

我已經做下面的代碼:

void Main() 
    { 
     // Both providers have static field Hash with default value. 
     // I expected that static fields should be initialized when application starts, 
     // then initialization will call CacheRepository.Register<T>() method 
     // and all classes will register them self in CacheRepository.RegisteredHashes. 

     // But code start working only when i created this classes (at least once) 
     // new ProviderOne(); 
     // new ProviderTwo(); 

     CacheRepository.Reset(); 
    } 

    public abstract class AbstractProvider 
    { 
     //... 
    } 

    public class ProviderOne : AbstractProvider 
    { 
     public static readonly string Hash = 
      CacheRepository.Register<ProviderOne>(); 

     //... 
    } 

    public class ProviderTwo : AbstractProvider 
    { 
     public static readonly string Hash = 
      CacheRepository.Register<ProviderTwo>(); 

     //... 
    } 

    public class CacheRepository 
    { 
     protected static Lazy<CacheRepository> LazyInstance = new Lazy<CacheRepository>(); 

     public static CacheRepository Instance 
     { 
      get { return LazyInstance.Value; } 
     } 

     public ConcurrentBag<string> RegisteredHashes = new ConcurrentBag<string>(); 

     public static string Register<T>() 
     { 
      string hash = typeof(T).Name; 

      if (!Instance.RegisteredHashes.Contains(hash)) 
      { 
       Instance.RegisteredHashes.Add(hash); 
      } 

      return hash; 
     } 

     public static void Reset() 
     { 
      foreach (string registeredHash in Instance.RegisteredHashes) 
      { 
       Instance.Reset(registeredHash); 
      } 
     } 

     protected void Reset(string hash); 
    } 



    interface IData{} 

    interface IDataProvider 
    { 
     string GetRedisHash(); 
     IData GetData(); 
    } 

    intefrace IRedisRepository 
    { 

    } 

如何使它的工作?

+1

您不一定需要創建實例。一旦任何靜態方法或屬性被調用,它們將被初始化。是否有什麼原因需要它們在你使用它們之前自動初始化? – TyCobb

+0

你可能想檢查這個問題。也許一個接口和一些反射會很好地與第二個答案:http://stackoverflow.com/questions/8748492/how-to-initialize-ac-sharp-static-class-before-it-is-actually-needed – TyCobb

+0

這個類是否需要自己註冊,或者你是否只想在加載dll時註冊類? – FriendlyGuy

回答

1

您可以直接訪問類的任何靜態方法/屬性 - 即Provider1.Name

public class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine(Provider1.Name + Provider2.Name); 
      Console.ReadLine(); 
     } 
    } 

在C#靜態構造函數(即初始化所有靜態字段)只稱爲如果類型的任何方法被用作覆蓋在C#規範中10.11 Static constructors

類的靜態構造函數在給定的應用程序域中最多執行一次。靜態構造函數的執行由應用程序域中發生的以下第一個事件觸發:
•創建了類的實例。
•引用該類的任何靜態成員。

請注意,神奇的註冊非常難以編寫單元測試 - 因此,儘管您的方法可行,但使用某些已知系統可以更好地註冊對象以方便測試。

+0

我試圖避免在一個地方創建一個與所有提供者的集合。這個想法是讓他們自給自足,而不是在代碼其他部分的其他地方直接聲明他們。從另一方面來說,我希望有一個簡單的刪除過程,而不會有人可以忘記排除已刪除的提供者 –