控制反转和选择

Inversion of Control and Choices

我正在尝试正确使用控制反转。我的应用程序运行良好。我使用 Unity 作为 IoC 容器。但是,当可以选择使用哪个具体 class 时,我认为我出错了。

在这个例子中,我有一个从特定数据源获取数据的 class。根据文件类型,我调用数据访问器 class.

此服务 class 检查类型,进行切换,然后选择要使用的具体 class。

但是,似乎我在这里违反了 IoC 原则,'newing' class 中的某些内容。我不再注入此服务 class,因为在这一点上,我还没有决定我正在使用哪种文件类型。所以我不得不注释掉 'injection',而是对其进行硬编码。

这是代码摘录。

public class DataService : IDataService
    {
        IFileReader _fileReader;
        public DataService(IFileReader fileReader)
        {
            // _fileReader = fileReader;
        }

        /// <summary>
        /// Returns reporting data based on a group of export files.
        /// </summary>
        /// <param name="files">A list of files to analyse</param>
        /// <returns></returns>
        private List<RawFileData> GetRawData(string[] files)
        {
            foreach (var file in files)
            {
                // validate files exists.
                switch (GetFileType(Path.GetFileName(file)))
                {
                    case "CSV":
                         {
                             fileIsOK = true;
                             _fileReader = new CSVileConnector();
                             break;
                         }
                     case "TXT":
                         {
                             fileIsOK = true;
                             _fileReader = new TXTFileConnector();
                             break;
                         }
                     default:
                         break;
                 }
                 if (fileIsOK)
                 {
                     var finedata = _fileReader.ReadData(file);
                     data.Add(new RawFileData
                     {
                         DataItems = finedata,
                         FileName = file
                     });
                }
            }

            return data;
        }

这是处理此类情况的正确方法吗?在 class 创建时,我不确定 child class 到 'depend' 是哪个?然后在逻辑上做出决定,并新建正确的Concrete class?

一个改进可能是将 reader 的选择与读取本身分开——一种称为 IFileReader _getDataReader(string filename) 的私有方法。所以在你的 foreach 循环中你说 var reader = _getDataReader(filename);。 reader 没有充分的理由在你的 class 中成为私有的 属性 因为它不是构造的,可以不断变化,并且它的使用范围仅限于 GetRawData.您 可以 考虑通过构造函数注入的是 class 在其接口定义中带有 GetDataReader(string) 。它本身可以包含一个私有的 Dictionary<string, Type>,它的密钥文件扩展名然后是该文件的 reader 作为值。如果您愿意,您甚至可以在 app.config 中配置它。这就是所谓的 Service Locator 模式。

出于各种原因,this is actually an anti-pattern 有很好的论据。也可能有人会说你想多了——因为你只有两个选择,而且这样读起来很容易——但是将 reader 的选择与阅读本身分开至少会让你陷入困境如果需要,可以更轻松地进行更改。