具有依赖倒置的架构(在 DI 框架之前)
architecture with Dependency Inversion (prior to a DI Framework)
我正在学习D.I。
我的架构有一些问题,也许我遗漏了一些要点。
假设我有这个非 DI 代码(我从文件中读取了 "Person" 的列表)
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 实现。
没关系?
或者我需要一个额外的 class,比如 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 to all.
编辑:
我展示了一个示例 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
}
}
PersonReaderFromFile
不依赖于 Person
。 class 似乎只是一个代表 运行 时间数据的 POCO。
PersonReaderFromFile
依赖于 StreamReader
以及 ParseInformationFromLine
函数
先抽象出那些实现细节到自己的关注点。
public interface IReadLines {
string ReadLine();
}
public interface IParsePersonInformationFromLine {
void ParseInformationFromLine(string line, out string name, out string lastName, out string email);
}
目标 class 将明确依赖于抽象
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;
}
}
各个抽象将有自己的实现来满足将在 运行 时使用的所需功能。例如 reader 内部仍会使用 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
}
可以应用进一步的重构,但这只是一个简化的示例,用于识别应该从与实现问题紧密耦合的代码中抽象出来的实现细节。
我正在学习D.I。 我的架构有一些问题,也许我遗漏了一些要点。
假设我有这个非 DI 代码(我从文件中读取了 "Person" 的列表)
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 实现。 没关系? 或者我需要一个额外的 class,比如 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 to all.
编辑: 我展示了一个示例 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
}
}
PersonReaderFromFile
不依赖于 Person
。 class 似乎只是一个代表 运行 时间数据的 POCO。
PersonReaderFromFile
依赖于 StreamReader
以及 ParseInformationFromLine
函数
先抽象出那些实现细节到自己的关注点。
public interface IReadLines {
string ReadLine();
}
public interface IParsePersonInformationFromLine {
void ParseInformationFromLine(string line, out string name, out string lastName, out string email);
}
目标 class 将明确依赖于抽象
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;
}
}
各个抽象将有自己的实现来满足将在 运行 时使用的所需功能。例如 reader 内部仍会使用 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
}
可以应用进一步的重构,但这只是一个简化的示例,用于识别应该从与实现问题紧密耦合的代码中抽象出来的实现细节。