具有依赖关系倒置的体系结构(DI框架之前)

时间:2020-03-30 14:49:38

标签: c# dependency-injection architecture dependency-inversion

我正在学习D.I. 我的架构存在一些问题,也许我遗漏了一些要点。

假设我有这个非DI代码(我从文件中读取了“人员”列表)

static void Main()
{
   PersonReaderFromFile personReader = new PersonReaderFromFile("path-to-file");
   Person p = personReader.GetNext();  //return a Person parsed from file line or NULL at EOF
}

class Person 
{
    //stuffs here
}

class PersonReaderFromFile
{
    public Person GetNext()
    {
        Person person = new Person();
        //some logic
        return person;
    }
}

首先,用于实施D.I.模式,我需要接口,所以我要做

static void Main()
{
   iPersonReader personReader = new PersonReaderFromFile("path-to-file");
   iPerson p = personReader.GetNext();
}

interface iPerson
{
}

class Person : iPerson
{
}

interface iPersonReader
{
    iPerson GetNext();
}

class PersonReaderFromFile : iPersonReader
{
    public iPerson GetNext()
    {
        Person person = new Person();
        //some logic
        return person;
    }
}

现在我的问题是:PersonReaderFromFile取决于Person的实现。 没关系? 还是我需要一个额外的类,例如PersonFactory?

static void Main()
{
    iPersonFactory factory = new PersonFactory();
    iPersonReader personReader = new PersonReaderFromFile("path-to-file", factory);
    iPerson person = personReader.GetNext();
}

interface iPerson
{
}

class Person : iPerson
{
}

interface iPersonReader
{
    iPerson GetNext();
}

class PersonReaderFromFile : iPersonReader
{
    iPersonFactory _factory;

    public PersonReaderFromFile(iPersonFactory factory)
    {
        _factory = factory;
    }

    public iPerson GetNext()
    {
        Person person = _factory.CreateNewPerson();
        //some logic
        return person;
    }
}

interface iPersonFactory 
{
    iPerson CreateNewPerson();
}

class PersonFactory : iPersonFactory
{
    iPerson CreateNewPerson()
    {
        Person person = new Person();
        return person;
    }
}

现在PersonFactory取决于Person实现,但是应该正确。 有什么建议吗? 向所有人发送Tnx。

编辑: 我展示了一个示例PersonReaderFromFile实现

class PersonReaderFromFile
{
    StreamReader _fileReader;

    public PersonReaderFromFile(string path)
    {
        _fileReader = new StreamReader(file);
    }

    public Person GetNext()
    {
        string line = _fileReader.ReadLine();
        if (line == null)
        {
                _fileReader.Close();
                return null;
        }

       string name, lastName, email;
       ParseInformationFromLine(line, out name, out lastName, out email);

       Person p = new Person { Name = name, LastName = lastName, Email = email };

       return p;
    }

   private ParseInformationFromLine(string line, out string name, out string lastName, out string email)
   {
        //I don't think that matters
   }
}

1 个答案:

答案 0 :(得分:1)

PersonReaderFromFile不依赖于Person。该类似乎只是表示运行时数据的POCO。

PersonReaderFromFile依赖于StreamReaderParseInformationFromLine函数

首先将这些实现细节抽象为他们自己关心的问题。

public interface IReadLines {
    string ReadLine();
}

public interface IParsePersonInformationFromLine {
    void ParseInformationFromLine(string line, out string name, out string lastName, out string email);
}

目标类将明确依赖抽象

public class PersonReaderFromFile {
    private readonly IReadLines reader;
    private readonly IParsePersonInformationFromLine parser;

    public PersonReaderFromFile(IReadLines reader, IParsePersonInformationFromLine parser) {
        this.reader = reader;
        this.parser = parser;
    }

    public Person GetNext() {
        string line = reader.ReadLine();
        if (line == null) {
            return null;
        }

        string name, lastName, email;
        parser.ParseInformationFromLine(line, out name, out lastName, out email);

        Person p = new Person { Name = name, LastName = lastName, Email = email };

        return p;
    }
}

各个抽象将具有自己的实现,以满足在运行时使用的所需功能。例如,读者在内部仍将使用StreamReader来获取行。 PersonReaderFromFile不需要了解有关如何检索行的任何信息。只是它在被调用时需要一条线。

Main现在可以重构为例如使用Pure DI

static void Main() {
    IReadLines reader = new ReadLinesImplementation("path-to-file");
    IParsePersonInformationFromLine parser = new ParsePersonInformationFromLine(); 
    PersonReaderFromFile personReader = new PersonReaderFromFile(reader, parser);
    Person p = personReader.GetNext();  //return a Person parsed from file line or NULL at EOF
}

还有其他可应用的重构,但这仅是标识实现细节的简化示例,应从与实现问题紧密相关的代码中抽象出这些细节。