I have a .NET 5.0 web application that instantiates classes for each of the endpoints. Those classes instantiate child classes. Is there a more elegant or efficient way to access parent instance data from child instances besides the way I'm doing it right now?
As an example:
public class ComponentClass
{
private PageClass _page;
public ComponentClass(PageClass page)
{
_page = page;
}
public void ComponentMethod()
{
// Call the method from the parent instance
page.PageMethod();
}
}
public class PageClass
{
private ComponentClass _component;
public PageClass()
{
_component = new ComponentClass(this);
}
public async Task ProcessRequest(HttpContext context)
{
// Call the component's method
_component.ComponentMethod();
}
public void PageMethod()
{
// Do something here
}
}
Specifically, I'm trying to avoid having to pass this
to every ComponentClass instance...
CodePudding user response:
If you want to call a method on the parent, then you have two options. The first is to pass a reference of the parent into the child. There's no way around this, an object has no way to know in which object it is referenced from. In fact, it could be referenced by multiple parent objects.
The better solution is to use events. That way the child never knows anything about the parent(s) and can emit events that any number of components can subscribe to. See here for more details on events. For example, your component could look something like this:
public class Component
{
public event EventHandler Tick;
public void DoSomething()
{
EventHandler handler = Tick;
handler?.Invoke(this, new EventArgs());
}
}
And your PageClass:
public class PageClass
{
public Component _component { get; set; }
public void Init()
{
_component = new Component();
_component.Tick = Component_Tick;
}
public void MakeComponentTick()
{
// This method is just for testing, it's likely this would be triggered by user input
_component.DoSomething();
}
private void Component_Tick(object sender, EventArgs e)
{
Console.WriteLine("Component ticked!");
}
}
CodePudding user response:
To make this classes loosly coupled and allow a compositon I would create several constructors and a special assign method. In the shortest variant you can create both classes in one line of code and you can select which class will be created the first
void Main()
{
var page = new PageClass();
page.ProcessRequest();
//or
var component = new ComponentClass();
component.ComponentMethod();
}
component class
public class ComponentClass
{
private PageClass _page;
public void AssignParent(PageClass page)
{
_page = page;
}
public ComponentClass(PageClass page)
{
AssignParent(page);
}
public ComponentClass(bool assignParent = true)
{
if (assignParent) AssignParent(new PageClass(false));
}
public void ComponentMethod()
{
// Call the method from the parent instance
_page.PageMethod();
}
}
page class
public class PageClass
{
private ComponentClass _component;
public PageClass(ComponentClass component)
{
AssignParent(component);
}
public PageClass(bool assignParent=true)
{
if(assignParent) AssignParent(new ComponentClass(false));
}
public void AssignParent(ComponentClass component)
{
_component = component;
_component.AssignParent(this);
}
public void ProcessRequest()
{
// Call the component's method
_component.ComponentMethod();
}
public void PageMethod()
{
// Do something here
}
}