问题
The Situation:
I have three classes: Society, Father and Son. The Society has a list of Fathers. Each Father has one son. It is necessary in this application that each Father knows who his Son is and vice-versa each Son knows who his Father is.
I have used direct cross referencing by assigning the Father as a property of the Son, and the Son as a property of the Father class, as below:
public class Society : ISociety
{
public List<IFather> Fathers {get; set;}
}
public class Father : IFather
{
public Father(ISon inp_son)
{
MySon = inp_son;
}
public ISon MySon {get; set;}
}
public class Son : ISon
{
public Son(IFather inp_father)
{
MyFather = inp_father;
}
public IFather MyFather {get; set;}
}
To manually implement dependency inversion, I have a public static class called Factory. The Factory returns interfaces of the Society, Father and Son classes through its methods. The methods instantiate Society, Father and Son classes and return them respectively as ISociety, IFather and Ison.
public static Factory
{
public static IFather CreateFather()
{
return new Father(CreateSon());
}
public static ISon CreateSon()
{
return new Son(CreateFather());
}
}
The application runs as follows.
.
.
.
IFather Father = Factory.CreateFather();
Society.Fathers.Add(Father);
.
.
.
The proeblem:
Every time the factory creates a Father, it instantiates a Son as its constructor input by invoking the CreateSon() method. When the CreateSon() method creates a Son, it invokes the CreateFather() method. This causes an endless loop, resulting in the StackOverFlow problem.
The big picture:
I have a large class library. In my library, higher-level classes have lists of lower-level classes. Calculations are performed inside the lower-level classes. The calculations need to access the properties of the higher-level classes. Therefore, the calculations need to somehow find their way to the higher level classes through the low-level class they belong to.
To be able to unit-test the code, I need to instantiate the Son class by passing the Factory.CreateFather()
in to the constructor of the Son.cs class. Doing so allows me to swap out the Father class with say Mother class in the Factory class without breaking the code.
I don't know of a more elegant way to allow the Son to know who the Father is other than these two ways:
1- The above-mentioned approach, which is cross referencing by directly assigning the MyFather property of the son.
2- Saving an identifier property of the Father (int number or Guid) in the Son. So the son can search for the Father by: Father MyFather = Society.Fathers[MyFathersNumber]. Given the list of Fathers is controlled not to have duplicates. The problem with this approach is that in a long chain of hierarchy, accessing a class several layers up becomes a difficult navigation and a lengthy line of code.
I had previously moved from way-2 to way-1 as a cleaner approach in the absence of dependency inversion. Now I am having StackOverFlow problem when I combine way-2 with the DI principle.
My Question:
Can someone please tell me what is the elegant way to let the Son know who his father is without causing a conflict with the Dependency Inversion Principle?
Thank you.
来源:https://stackoverflow.com/questions/61794493/stackoverflow-in-the-implementation-of-the-dependency-inversion-principle-for-cr