实现依赖注入和接口的问题

时间:2020-06-19 11:25:40

标签: c# dependency-injection interface

我试图了解依赖注入和接口,但遇到一个奇怪的问题。

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()方法的末尾,我将有一个列表,其中该列表中的每个对象都将具有不同的文件路径。

foreach(var file in files)
{
    Console.WriteLine(file.Filepath);
}

output:
path1
path2
path3
path4
path5

相反,ProcessFiles()方法返回的列表中的每个对象都填充有该方法循环通过的 last 文件路径的文件路径。结果是这样的:

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接口的任何特定类?

1 个答案:

答案 0 :(得分:0)

您当前正在将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;
    }
}
相关问题