繁体   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