c# - 实现依赖注入和接口的问题
问题描述
我试图了解依赖注入和接口,但我遇到了一个奇怪的问题。
https://dotnetfiddle.net/5vfcd0
我有一个接口和一个实现该接口的模型:
public class FileModel : IFileModel
{
public string Filepath {get;set;}
}
public interface IFileModel
{
string Filepath {get;set;}
}
我还有一个 FileProcessor 类,它处理实现 IFileModel 接口的对象:
public class FileProcessor
{
private static IFileModel _file;
public FileProcessor(IFileModel file)
{
_file = file;
}
public List<IFileModel> ProcessFiles(List<string> filepaths)
{
List<IFileModel> output = new List<IFileModel>();
foreach(string path in filepaths)
{
_file.Filepath = path;
output.Add(_file);
}
return output;
}
}
在我的 Main() 方法中,我创建了一个虚拟文件路径列表。然后,我创建 FileProcessor 的一个实例,并将 FileModel 的一个新实例作为参数提供给 FileProcessor 的构造函数。我这样做是为了向 FileProcessor 指定我要处理的文件类型。
我调用 FileProcessor 实例的 ProcessFiles() 方法,该方法将文件路径列表作为参数。ProcessFiles() 循环遍历文件路径并创建 IFileModel 对象列表并返回该列表。
public static void Main()
{
List<string> filepaths = new List<string>();
filepaths.Add("path1");
filepaths.Add("path2");
filepaths.Add("path3");
filepaths.Add("path4");
filepaths.Add("path5");
FileProcessor fileProcessor = new FileProcessor(new FileModel());
List<IFileModel> files = fileProcessor.ProcessFiles(filepaths);
foreach(var file in files)
{
Console.WriteLine(file.Filepath);
}
}
我的假设是,在 Main() 方法的末尾,我会有一个 List,其中该列表中的每个对象都有不同的文件路径。
foreach(var file in files)
{
Console.WriteLine(file.Filepath);
}
output:
path1
path2
path3
path4
path5
相反,ProcessFiles() 方法返回的列表中的每个对象都填充有该方法循环通过的最后一个文件路径的文件路径。结果是这样的:
path5
path5
path5
path5
path5
我创建了一个小提琴来演示这个问题。https://dotnetfiddle.net/5vfcd0
如果我在 ProcessFiles() 方法中实例化一个新的 FileModel,它会按预期工作。但我不希望 FileProcessor 依赖于 IFileModel 的特定实现。
public List<IFileModel> ProcessFiles(List<string> filepaths)
{
List<IFileModel> output = new List<IFileModel>();
foreach(string path in filepaths)
{
_file = new FileModel(); // dependency
_file.Filepath = path;
output.Add(_file);
}
return output;
}
我究竟做错了什么?我应该如何修复这个实现,以便 FileProcessor 不依赖于任何实现 IFileModel 接口的特定类?
解决方案
您目前正在将一个实例传递FileModel
给您的FileProcessor
班级并将其添加到列表中 5 次。
每次,您都在更新Filepath
同一个实例。
您可能想要做的是注入工厂方法:
public class FileProcessor
{
private static Func<IFileModel> _fileFactory;
public FileProcessor(Func<IFileModel> fileFactory)
{
_fileFactory = fileFactory;
}
public List<IFileModel> ProcessFiles(List<string> filepaths)
{
List<IFileModel> output = new List<IFileModel>();
foreach(string path in filepaths)
{
var file = _fileFactory();
file.Filepath = path;
output.Add(file);
}
return output;
}
}
然后调用如下:
var fileProcessor = new FileProcessor(() => new FileModel());
或者更好的是,为您的工厂创建一个接口:
interface IFileModelFactory
{
FileModel CreateModel();
}
实施:
class FileModelFactory
{
public FileModel CreateModel() => new FileModel();
}
并注入:
public class FileProcessor
{
private static IFileModelFactory _fileFactory;
public FileProcessor(IFileModelFactory fileFactory)
{
_fileFactory = fileFactory;
}
public List<IFileModel> ProcessFiles(List<string> filepaths)
{
List<IFileModel> output = new List<IFileModel>();
foreach(string path in filepaths)
{
var file = _fileFactory.CreateModel();
file.Filepath = path;
output.Add(file);
}
return output;
}
}
推荐阅读
- kubernetes - k8s readiness and liveness probes failing even though the endpoints are working
- c++ - 是否存在将非 ADL 名称查找推迟到使用 C++ 概念的技巧?
- java - Spring Boot 测试,多个测试类按特定顺序运行(类顺序,而不是方法顺序)
- spring-security - 使用自己的 ldif 文件时出现 LDAP 异常
- php - Docker: How can I run a Wordpress project with specific versions?
- typescript - 重载的返回类型不能正常工作
- cordova - Cordova iOS 通用链接打开特定页面没有插件
- android - 亚行拉取目录的所有内容,但不是来自android的目录并复制到windows
- installation - 选择 CHF 作为默认货币时,Shopware 6 安装期间出现 SQL 错误
- java - 如何让这段代码一直问一个数字,直到找到一个素数?