So here is my setup and the comment shows what I wish to do:
class Process
{
void SomeMethod()
{
// Here I want to call Parent.MethodToCall()
}
}
class Controller
{
Process c = new Process();
void MethodToCall()
{
}
}
Now the Controller.MethodToCall() will be called many times throughout the lifecycle of the Process class.
It is only the parent method that needs to be called so I believe that using an event would be a bit wasteful as I will never be removing the handler and there would only be one invocation.
So the way I am currently using to get around this is like follows:
class Process
{
public Func<void> Method { get; set; }
void SomeMethod()
{
Method();
}
}
class Controller
{
Process c = new Process() { Method = MethodToCall }
void MethodToCall()
{
}
}
First off, the syntax might not be perfect, I quickly knocked it up in notepad.
My question: What is the best way to achieve what I want because what I am doing looks quite messy to be?...or am I thinking about this completely the wrong way in terms of design?
Essentially what I want to do is call a method in the Controller class without making it public, because if it is public, I could simply pass the Controller as a parameter to the Process.
class Child
{
Parent parent=null;
public Child(Parent p)
{
parent=p;
}
void SomeMethod()
{
parent.MethodToCall();
}
}
This should be a good example of how to do that
class Child : Parent
{
private void SomeMethod()
{
base.MethodToCall();
}
}
class Parent
{
Child c = new Child();
protected void MethodToCall()
{
c.MethodToCall();//not sure if you are wanting to call c.MethodToCall();
}
}
Well, in OOP terms the correct answer would be the following:
class Child : Parent
{
void SomeMethod()
{
base.MethodToCall();
}
}
class Parent
{
protected void MethodToCall()
{
// protected methods are accesible from
// descendants and private from outside
}
}
But you can always avoid inheritance, using aggregation
What you are doing is essentially rolling your own events. Internally, event handlers are just delegates attached to the event, with the one difference that only the owner of the event can raise it.
Related
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...
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!");
}
}
I think my question is best descirbed by a code snippet:
class A
{
public void FunctionToBeCalled();
}
class B
{
public void FunctionToBeCalledAfter();
}
Now, after a FunctionToBeCalledAfter() call, FunctionToBeCalled() needs to "know" it must be called. B cannot have an A member, but A can have a B member. Is there any way this can be implemented in C#?
Why i need this:
Class A is Application level on OSI stack. Classes B and C(unmentioned before) are Transport Level. C makes calls to FunctionToBeCalledAfter, and after this FunctionToBeCalled needs to be called. But sincer A is a higher level, B and C cannot depend(have a member A), i don't know how to call FunctionToBeCalled.
I see 2 ways to accomplish this, one easier but (arguably) less elegant, one a little more involved but (arguably) more elegant
The less elegant solution: Singleton
A Singleton pattern enforces that there can only ever be one instance of a class at any given time, this seems to line up with your description of A (which from here on out I'll call Foo, and I'll be calling B Bar). So let's implement it:
public class Foo
{
private static Foo _instance;
public static Foo Instance => _instance ?? (_instance = new Foo());
// Private constructor so no one else can instantiate Foo
private Foo() { }
public void FunctionToBeCalled() { /* your code here */ }
}
public class Bar
{
public void FunctionToBeCalledAfter()
{
// Your existing code here
Foo.Instance.FunctionToBeCalled();
}
}
Now, the problem here is if your requirements ever change and you need multiple Foos, that'll be quite a refactor to implement it. Another (larger) downside is that we explicitly reference (i.e depend on) Foo, which isn't great and a problem if Bar is inside a project/ library that cannot directly reference Foo. Luckily solution 2 fixes those problems:
The more elegant solution: Events
public class Foo
{
// We don't need Foo to be a singleton anymore
public void FunctionToBeCalled() { /* Your code here */ }
}
public class Bar
{
public delegate void FunctionToBeCalledAfterEventHandler();
public event FunctionToBecalledAfterEventHandler FunctionToBeCalledAfterEvent;
public void FunctionToBeCalledAfter()
{
// Your existing code here
OnFunctionToBeCalledAfterEvent(); // Fire the event
}
private void OnFunctionToBeCalledAfterEvent()
{
FunctionToBeCalledEvent?.Invoke();
}
}
Now, everywhere where you're creating an instance of Bar you need to have a reference to Foo and subscribe to the event like so:
// foo = instance of class Foo
var bar = new Bar();
// The compiler is smart enough to find out that 'FunctionToBeCalledAfterEvent'
// has the same signature as 'FunctionToBeCalledAfterEvent' and can call it directly
// If this just so happens to not be case, see second way to subscribe to events
bar.FunctionToBeCalledAfterEvent += foo.FunctionToBeCalled;
// Or
bar.FunctionToBeCalledAfterEvent += () => foo.FunctionToBeCalled();
Events are great
Class B can have an event that other parties can handle. At the end of B.FunctionToBeCalledAfter this event would be invoked. Anyone who registered for this event would then be notified. Usual boilerplate code involves one virtual method that invokes one event. It's the standard way of adding events. If there is no need for additional data in the event then EventArgs is used. If additional data is needed then you could replace EventArgs with EventArgs<YourData>, or as an alternative, introduce a class XxxArgs derived from EventArgs with this additional data.
Class B
{
public event EventHandler FinishedFunctionToBeCalledAfter;
protected virtual void OnFinishedFunctionToBeCalledAfter(EventArgs e)
{
EventHandler handler = FinishedFunctionToBeCalledAfter;
handler?.Invoke(this, e);
}
public void FunctionToBeCalledAfter()
{
...
OnFinishedFunctionToBeCalledAfter(EventArgs.Empty);
}
}
Now when class A gets a hold of an object of class B it would add its event handler to it:
class A
{
public void FunctionToBeCalled();
public void FinishedFunctionToBeCalledAfter(object source, EventArgs e);
public void IntroduceObject(B b)
{
b.FinishedFunctionToBeCalledAfter += FinishedFunctionToBeCalledAfter;
}
}
When this object b of class B should end its life class A must know about it so that it can remove its event handler:
b.FinishedFunctionToBeCalledAfter -= FinishedFunctionToBeCalledAfter;
suppose we have this scenario :
a class that you are not allowed to modify anything in it :
public class ForbiddenClass_A
{
public void TheMethod()
{
//do stuff
}
}
and another read only class that calls a method from the previous class:
public class ForbiddenClass_B
{
ForbiddenClass_A fc_a;
void Update()
{
//some logic that if true it will call :
fc_a.TheMethod();
}
}
Now you have your class, that you do anything to it, and from it you want to know if TheMethod() :
public class MyClass
{
//call this when TheMethod() from ForbiddenClass_A is called.
public void TheMethod_Catcher()
{
}
}
Thank you!
Is there a way to catch a method call without subscribing it to any
sort of Events?
Decoupled messaging is probably where you want to be, event aggregator or any other pub sub method messaging system. Although you still have to subscribe to something, the participants need not know about each other allowing you to make the methods private.
Unity, MvvmLight both have these sorts of messaging systems, however they are truly dime-a-dozen, there are plenty
Example of how this might work
public CreateUserForm()
{
InitializeComponent();
EventPublisher.Instance.Subscribe<NewUserCreated>
(n => listBoxUsers.Items.Add(n.User.Name));
}
...
// some other class
private void Update()
{
var user = new User()
{
Name = textBoxUserName.Text,
Password = textBoxPassword.Text,
Email = textBoxEmail.Text
};
EventPublisher.Instance.Publish(new NewUserRequested(user));
}
Update
There are injection techniques if you are interest for .net
Dynamically replace the contents of a C# method?
I was wondering how I should decide to create an object, on method or class instance.Below a few examples to clarify. I want to the best approach to know how I should determine to choose between example 1 and 2.
IMPORTANT: Consider this a Windows Service (SVC) hosted in IIS.
Example 1
public class mySvcService
{
ReusableClass rClass = new ReusableClass();
public void MethodOne()
{
//Do Method One Stuff...
rClass.doSomething();
}
public void MethodTwo()
{
//Do Method Two Stuff...
rClass.doSomething();
}
}
public class ReusableClass
{
string valueOne;
string valueTwo;
string valueThree;
public void doSomething()
{
//DoSomeWork
}
}
Example 2
public class mySvcService
{
public void MethodOne()
{
ReusableClass rClass = new ReusableClass();
//Do Method One Stuff...
rClass.doSomething();
}
public void MethodTwo()
{
ReusableClass rClass = new ReusableClass();
//Do Method Two Stuff...
rClass.doSomething();
}
}
public class ReusableClass
{
string valueOne;
string valueTwo;
string valueThree;
public void doSomething()
{
//DoSomeWork
}
}
It is all about state. Will the object preserve some state between the two method calls, or even within the method, or not? If so, you should keep the object alive. Else, you can create a new object every time you call the method, or maybe even make the method static if there is never any state involved.
So:
Class preserves state that should be kept across methods: make a class variable or pass the object along the methods.
Class preserves state that should be kept within the same method: make a local variable.
Class doesn't preserve any state: make the method static, no instance needed.
The golden rule is to keep the scope as local as possible. From the second example if you are going to use doSomething() everywhere then it is better to create it once and have class level scope. If you need doSomething() only in one method, create the object locally within the method.
It is better to leave it inside of a method. Usually, it is being done inside of the constructor. This has the favor that it can incorporate a factory for different scenarios, or that it can be easily injected. I would strongly suggest to separate the responsibilities of the properties and let them be used as needed.
If you want to limit the scope of the object to a method, It can be done by using "Method injection" as shown below. You can use the other setter and constructor injection methods if the scope of the object is through out the class.
public interface IReusable
{
void doSomething();
}
public class Reusable: IReusable
{
public void doSomething()
{
//To Do: Some Stuff
}
}
public class mySvcService
{
private IReusable _reuse;
public void MethodOne(IReusable reuse)
{
this._reuse= reuse;
_reuse.doSomething();
}
public void MethodTwo(IReusable reuse)
{
this._reuse= reuse;
_reuse.doSomething();
}
}
Maybe overloading a method is not exactly what is necessary but this is the best i could come up with.
I have a class:
public class Worker {
private string jobType;
public Worker(string jt)
{
this.jobType = jt;
}
public void ProcessJob()
{
if(jobType.Equals("Pizza") MakePizza();
else if (jobType.Equals("Burger") MakeBurger();
}
private void MakePizza()
{
// make pizza
}
private void MakeBurger()
{
// make burger
}
}
The above is just an example of illustration. When the class is constructed, it is constructed with a specific job type, and that won't change. However it may need to perform millions of jobs, always of the same type. The ProcessJob() will be called all the time, but the caller won't know what type of worker this is. I would like to avoid running the if check every single time, there has to be a way to do that check only once and prep it.
In my case, making child classes (pizza worker, burger worker, etc.) is not an option, as in my real case, the class is large and there is only one tiny difference. Changing it will impact the whole architecture so it needs to be avoided.
Create an abstract base class, which contains common things a worker can do. Then declare derived classes for specialized workers.
public abstract class Worker
{
public abstract void ProcessJob();
}
public class PizzaWorker : Worker
{
public override void ProcessJob()
{
// Make pizza
}
}
public class BurgerWorker : Worker
{
public override void ProcessJob()
{
// Make burger
}
}
Now you can create workers of different types and let them do their job:
var workers = new List<Worker>();
workers.Add(new PizzaWorker());
workers.Add(new BurgerWorker());
foreach (Worker worker in workers) {
woker.ProcessJob();
}
This will automatically call the right implementation of ProcessJob for each type of worker.
Note: If-else-if cascades and switch statements are often an indication that the code works in a procedural rather than object-oriented way. Refactor it to be object-oriented!
You could use a delegate created when the object is constructed, this way the dispatch is done automatically:
public class Worker
{
private delegate void MakeSomething();
private MakeSomething makeWhat;
private string jobType;
public Worker(string jt)
{
this.jobType = jt;
switch (jt)
{
case "Pizza":
makeWhat = new MakeSomething(MakePizza);
break;
case "Burger":
makeWhat = new MakeSomething(MakeBurger);
break;
default:
throw new ArgumentException();
}
}
public void ProcessJob()
{
makeWhat();
}
private void MakePizza()
{
//make pizza
}
private void MakeBurger()
{
//make burger
}
}
I would still recommend to use sub classes. If you cannot inherit from Worker then create new class hierarchy that is used inside the worker. This way anyone using Worker class doesn't have to know that there are sub classes. If you really really hate sub classes or you have some other reason you don't want them you can use dictionary. It contains job type as key and Action as the method it calls. If you need more jobs just create the private method and register it in the RegisterWorkers method.
private Dictionary<string, Action> actions = new Dictionary<string, Action>();
public Worker(string jt)
{
this.jobType = jt;
this.RegisterWorkers();
}
private void RegisterWorkers
{
this.actions["Pizza"] = this.MakePizza;
this.actions["Burger"] = this.MakeBurger;
}
public void ProcessJob()
{
var action = this.actions[this.jobType];
action();
}
No, I don't think it should be avoided. Any common functionality should go in a base class. I think you need a static factory method, that returns a child class based on the string parameter.
public abstract class Worker {
public virtual void ProcessJob();
public static Worker GetWorker(string jobType) {
if(jobType.Equals("Pizza")
return new PizzaWorker();
else if (jobType.Equals("Burger")
return new BurgerWorker();
else
throw new ArgumentException();
}
// Other common functionality
protected int getFoo() {
return 42;
}
}
public class PizzaWorker : Worker {
public override void ProcessJob() {
// Make pizza
int y = getFoo() / 2;
}
}
public class BurgerWorker : Worker {
public override void ProcessJob() {
// Make burger
int x = getFoo();
}
}
So to use this:
Worker w = Worker.GetWorker("Pizza");
w.ProcessJob(); // A pizza is made.
This is exactly why there are patterns: Command, Strategy, Decorator.
I believe the command pattern is what you are looking for. First you have a basic 'command' template:
public interface IJob {
void ProcessJob();
}
Different jobs would then be performed as follows:
public class MakePizza : IJob {
// implement the interface
public void ProcessJob() {
// make a pizza
}
}
Now, you could have a JobFactory as follows:
public static class JobFactory {
public static IJob GetJob(string jobType) {
if(jobType.Equals("Pizza"){
return new MakePizza();
} else (jobType.Equals("Burger") {
return new MakeBurger();
}
// to add jobs, extend this if-else-if or convert to switch-case
}
}
Worker can now look like this:
public class Worker {
private IJob job;
public Worker(string jt) {
job = JobFactory.GetJob(jt);
}
public void ProcessJob() {
job.ProcessJob();
}
}
If you don't have access to code to make these changes, then another pattern you may want to look into is the Adapter.
You're talking about basic inheritance here. There are a couple of ways that you could do this.
Make a Base Class that is
public class Job
{
virtual void ProcessJob();
}
Then a MakePizza class
public class MakePizza : Job
{
public void ProcessJob()
{
//make Pizza
}
}
Then in your worker class instead of having a JobType as a string which will lead to all kinds of potential bugs.
public class Worker{
private Job jobType;
public Worker(Job jt){
this.jobType = jt;
}
public void ProcessJob()
{
Job.ProcessJob();
}
}
If you have to pass through a string you could simply load up the JobType through reflection, throwing a error if the type doesn't exist.
having to change other classes means you need to change code, not that you need to change architecture. the best answer is just to change the code. in the long term, the maintenance burden of having to write this in a less-than-ideal fashion will cost you more than just changing the code. use inheritance and bite the bullet on making the change now. if you have iterators that will have problems with dealing with subtypes, your iterators are doing more than being iterators, and you are better off fixing that than going forward with them. if the other classes care about what subtype of worker they are dealing with, that's a problem in and of itself that you should fix. ultimately, the dependent code should not care which type of worker it is. that's really what you are after anyway. the instance of a type that has work as its base type is still a worker and that is all the class using a worker should care about.