Проблема с внедрением зависимостей и интерфейсов - PullRequest
0 голосов
/ 19 июня 2020

Я пытаюсь понять, что такое внедрение зависимостей и интерфейсы, но у меня возникает странная проблема.

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, какие файлы я собираюсь обрабатывать.

Я вызываю метод ProcessFiles () экземпляра FileProcessor, который принимает список путей к файлам в качестве параметра. 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

Если я создаю экземпляр новой FileModel в методе ProcessFiles (), он будет работать, как задумано. Но я не хочу, чтобы FileProcessor зависел от конкретной c реализации 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 не зависел от какого-либо определенного c класса, реализующего интерфейс IFileModel?

1 Ответ

0 голосов
/ 19 июня 2020

В настоящее время вы передаете один экземпляр 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;
    }
}
...