Suppose I have 2 classes, A and B. Class A is responsible for "finding/generating" objects of B, so it has some methods that create and return instances of B. Class B has methods that find objects of B that are somewhat related to its instance. Say finding its parent or siblings.
In order to illustrate the situation, suppose that class A is PersonFinder (the only class throuth which one can find a Person) and class B is Person (has children, instances of Person, who can only be found throuth PersonFinder).
The way I thought I could implement this is:
Class A/PersonFinder:
public class PersonFinder
{
//For the sake of simplicity suppose each person has an unique name
public Person FindPersonByName(string name)
{
//Some code
return new Person(name, this);
}
}
Class B/Person:
public class Person
{
public string Name {get;set;}
private string childName {get;set;} //For the sake of simplicity, suppose each person has a child and that it knows the its name
private PersonFinder _personFinder {get;set;}
public Person(string name, PersonFinder personFinder)
{
Name = name;
_personFinder = personFinder;
}
public Person GetChild()
{
return _personFinder.FindPersonByName(childName);
}
}
It works, but I have two questions about it:
1- Is this a proper design? Is there a better way to do it?;
2- Suppose class A/PersonFinder implements IDisposable. According to MS documentation, if a class has an instance of a class that implements IDisposable, then it should implement IDisposable as well. So should class B/Person implement it? If so, then calling Dispose() on an instance of Person would dispose the PersonFinder of all Persons... Would this be an exception to this rule?.
Thanks in advance!
Implementing
IDisposableand disposing is about ownership, i.e. who owns and controls the lifetime of the dependency. In this particular casePersoninstance will not have the ownership of passedPersonFinderwhich potentially will be shared between different instances, soPersonshould not dispose it (and subsequentially implementIDisposable) in this case.If you are instantiating an instance of
PersonFinderperPersonlikenew Person(..., new PersonFinder())then you should implement theIDisposableand dispose. If both patterns can be present then you can add additional parameterbool disposewhich will control the usage (this pattern can be seen in some libraries including framework ones likeStreamReader'sleaveOpen).Somewhat similar is the build-in DI and the factory pattern relationship, for example EF Core's
DbContextfactory - when something (likeDbContext) is created via DI then the container has ownership of the lifetime and it will handle disposingIDisposable's, but for theDbContextfactory pattern it is not the case:This is bit more opinionated question. Personally I would go with slightly more decoupled design by making
childNamepublic and when child is needed grabbing the instance ofPersonFinderandPersonand just use the corresponding methods, (i.e.somePersonFinder.FindPerson(person.ChildName)) but without full understanding of the code is actually hard to tell (though if you can't/don't want to exposechildNamein some way for some reason then the only alternative option is to passPersonFinderto theGetChildmethod).