我正在尝试正确使用控制反转。我的应用程序运行良好。我使用 Unity 作为 IoC 容器。但是,当可以选择使用哪个具体类时,我认为我出错了。
在这个例子中,我有一个从特定数据源获取数据的类。根据文件类型,我调用数据访问器类。
此服务类检查类型、进行切换,然后选择要使用的具体类。
但是,似乎我在这里通过在类里面“更新”一些东西来打破 IoC 原则。我不再注入(inject)这个服务类,因为在这一点上,我还没有决定我正在使用哪种文件类型。所以我不得不注释掉“注入(inject)”,而是对其进行硬编码。
这是一段代码摘录。
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)时,我不确定要“依赖”哪个子类(class)?然后在逻辑上决定它,并新建正确的 Concrete 类?
最佳答案
一个改进可能是将读者的选择与阅读本身分开——一个名为 IFileReader _getDataReader(string filename)
的私有(private)方法。 .所以在你的 foreach 循环中你说 var reader = _getDataReader(filename);
.读者没有充分的理由成为您类(class)中的私有(private)属性(property),因为它不是构造的,可以不断变化,并且其使用范围仅限于 GetRawData
。 .您可以考虑通过构造函数注入(inject)的是一个带有 GetDataReader(string)
的类在其接口(interface)定义中。它本身可以拥有私有(private) Dictionary<string, Type>
它将以文件扩展名作为键,然后将该文件的读者作为值。如果你愿意,你甚至可以在你的 app.config 中配置它。这就是所谓的 Service Locator模式。
有很好的论据表明 this is actually an anti-pattern由于各种原因。也可能有人会说你想多了——因为你只有两个选择,而且这样阅读很容易——但是将读者的选择与阅读本身分开至少会让你更容易如果需要,可以更改。
关于c# - 控制反转和选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42405147/