簡體   English   中英

如何在C#中安全地將靜態類轉換為實例化類

[英]How can I safely convert a static class to an instantiated class in C#

我最近(幾個月前)改變了工作,繼承了一個代碼庫,它違反了SOLID原則的每一個,盡可能多次。 似乎編寫此代碼的人決定詳細研究每一個良好的編碼實踐,並盡可能經常地和最根本地違反它們。

我是該產品的唯一開發人員 - 組織中沒有人知道代碼,代碼庫太大而且復雜,無法完全重寫。 我正在研究可以使代碼庫變得靈活和健壯的最高價值變化。 放棄此產品也不是一種選擇。

產品中所有問題的根源於一組類,這些類是核心業務邏輯數據結構。 這些類有很多問題,但我真正感興趣的是以下內容:

public static class NetCollection
{
    private static Logger LogFile { get { return Logger.GetMethodLogger(2); } }
    // Declare local variables.
    private static Dictionary<string, NetObject> netObjectHashTable;
    private static Dictionary<string, NetTitle> titlePropertyHashTable;
    private static Dictionary<string, NetObject> referenceDataHashTable;
    private static Dictionary<int, SortedDictionary<string, int>> picklistHashTable;

    public static IEnumerable<NetObject> NetObjects
    {
        get
        {
            return netObjectHashTable.Values;
        }
    }

    static NetCollection()
    {
        netObjectHashTable = new Dictionary<string, NetObject>();
        titlePropertyHashTable = new Dictionary<string, NetTitle>();
        referenceDataHashTable = new Dictionary<string, NetObject>();
        picklistHashTable = new Dictionary<int, SortedDictionary<string, int>>();
    }

    public static void AddNetObject(NetObject newObject)
    {
        if (newObject == null)
            return;
        if (newObject.TitleType == "Reference Data")
        {
            // Check if hash table contains key
            if (!referenceDataHashTable.ContainsKey(newObject.ID.ToString()))
            {
                referenceDataHashTable.Add(newObject.ID.ToString(), newObject);
            }
        }
        else
        {
            // Check if hash table contains key
            if (!netObjectHashTable.ContainsKey(newObject.ID.ToString()))
            {
                netObjectHashTable.Add(newObject.ID.ToString(), newObject);
            }
        }
    }
}

為了簡潔起見,我已經從這個類中剪切了很多其他方法。

正如你所看到的,這個類周圍存在大量問題(在靜態類中存儲狀態是一個巨大的代碼味道 - 圍繞所述類編寫整個應用程序只是瘋了)。

我目前的意圖是將這個類重構為一個合適的單例類(並最終進入一個常規類,這樣我就可以讓用戶同時打開多個文檔)。

我應該這樣做嗎?

進行此項更改的最大風險是什么? 我是否可以采取任何方法來降低進行此更改的風險?

是的,轉換為單身似乎是一個良好的第一步。 它仍然不是線程安全的,但它是一個開始。 然后,您可以將其從真正的單例更改為允許構造單獨實例的單例,但也可以像單例一樣使用“默認”實例。 (當然,你可以將“實例持有者”分成一個單獨的類。)這將允許你開始編寫可測試代碼,每次都以一個新實例開始。

之后,您可以開始引入依賴注入,以便需要訪問同一實例的每個類獲取它...並刪除“默認”實例。

當然,如果你可以減少需要訪問同一個實例的類的數量,那也會更好。

對於線程,您需要鎖定每個方法,或使用ConcurrentDictionary

如果您對應用程序中此類型的流程一無所知,那將是一項危險的任務。 但如果你真的需要這樣做,可能會打破一切,我會這樣做:

知道我需要的是文檔之間的明顯划分,我知道(這已經證明了時間)這種類型適用於單個文檔,讓我們添加Document slice。

假設DocumentName屬性,我們可以考慮像(例子)這樣的東西:

public static void AddNetObject(string documentName, NetObject newObject)
{
    ....
}

使所有字段靜態:

   //NO STATIC
    ...
    private Logger LogFile { get { return Logger.GetMethodLogger(2); } }   
    private Dictionary<string, NetObject> netObjectHashTable;
    private Dictionary<string, NetTitle> titlePropertyHashTable;
    private Dictionary<string, NetObject> referenceDataHashTable;
    private Dictionary<int, SortedDictionary<string, int>> picklistHashTable;

將它們移動到內部

private class NetDocument {
       public string DocumentName {get;set;} //DEFINE DOCUMENT IT RELATED TO !
       ...
       private Logger LogFile { get { return Logger.GetMethodLogger(2); } }   
       private Dictionary<string, NetObject> netObjectHashTable;
       ....

  }

因此,您可以在單個文檔之間創建具體的隔離,並與它們相關。

在主類里面后你可以有:

public static class NetCollection
{
    ... 

    //Key: document name
    //Value: NetDocument data
    private Dictionary<string, NetDocument> documents = new ....
}

這只是一個概念(草圖),您肯定需要根據自己的需要進行更改

你可以將它包裝在一個靜態的Factory類中嗎? 制作你認為自己需要的所有單件,並根據需要保持某些東西靜止? 它將解決一些問題,並為您提供一些靈活性。

static類和Singleton之間沒有真正的區別。 是的,它的實現方式不同,但你有同樣的問題(只是為了沒有static我不認為這是必要的行為)。

如果你能夠找到“真實”的實例,那就去做吧。 但只是重構單身,因為林特不抱怨不是恕我直言的方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM