I really am not sure what else to google to try to find the answer to this, can anyone tell me the proper way to implement these events? In ClassOne the event is considered null, and I just don't get it ....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MultipleInheritance
{
static class Program
{
static void Main()
{
ClassThree cThree = new ClassThree();
cThree.fireEventOne += cThree_fireEventOne;
cThree.Start();
cThree.Start2();
cThree.Start3();
}
static void cThree_fireEventOne()
{
Console.WriteLine("one two three");
}
}
}
and here is the classes
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MultipleInheritance
{
public abstract class ClassOne
{
public delegate void EventOne();
public event EventOne fireEventOne;
public ClassOne()
{
}
public void Start()
{
fireEventOne();
}
public abstract void Start2();
}
public abstract class ClassTwo :ClassOne
{
public delegate void EventOne();
public event EventOne fireEventOne;
public override void Start2()
{
fireEventOne();
}
public abstract void Start3();
}
public class ClassThree :ClassTwo
{
public delegate void EventOne();
public event EventOne fireEventOne;
public override void Start3()
{
fireEventOne();
}
}
}
The problem is that you're redefining the following in each class:
public delegate void EventOne();
public event EventOne fireEventOne;
So when you call Start() you are trying to fire the event fireEventOne in the class ClassOne, but you've hooked up the shadowed event in ClassThree like this:
cThree.fireEventOne += cThree_fireEventOne;
I can see why you coded it that way. You get a compiler error when trying to directly invoke the event from a parent class. The correct way is to provide a protected method that you call in the parent class to fire the event.
Try writing your classes like this:
public abstract class ClassOne
{
public delegate void EventOne();
public event EventOne fireEventOne;
public ClassOne()
{ }
public void Start()
{
this.DoFireEventOne();
}
protected void DoFireEventOne()
{
var feo = fireEventOne;
if (feo != null)
{
feo();
}
}
public abstract void Start2();
}
public abstract class ClassTwo :ClassOne
{
public override void Start2()
{
this.DoFireEventOne();
}
public abstract void Start3();
}
public class ClassThree :ClassTwo
{
public override void Start3()
{
this.DoFireEventOne();
}
}
You create the fireEventOne event in each class. So, you have three events. But, the fireEventOne method is implemented on the first level (ClassOne). So, it will raise the delegate of the ClassOne class. Remove the fireEventOne event for the descendant classes.
Related
I have a base class implementing an interface and further a specialized class inheriting the base class.
I have implemented interface's method in base class and marked it as virtual, also overridden the same method in specialized class.
Now i want to resolve the method GetData() on some basis that it either returns base class's method or child class's method.
So basically how can I call base class method using the specialized class's reference or interface's reference?
Edit 1
I have an existing data provider and I want to keep its functionality as it is and want to use some subclass or wrapper class where i can write a new implementation(another provider), mind that I want to keep running existing provider as it is for existing scenario and the new provider for other scenarios). what if i use decorator pattern to solve this? Any other pattern which can solve this ?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
interface IDataProvider
{
void GetData();
}
abstract class StandardDataProvider : IDataProvider
{
public virtual void GetData()
{
Console.WriteLine("GetData_StandardDataProvider");
}
}
class ManagedDataProvider : StandardDataProvider
{
public override void GetData()
{
Console.WriteLine("GetData_ManagedDataProvider");
}
}
class Program
{
static void Main(string[] args)
{
IDataProvider dataprovider = new ManagedDataProvider();
dataprovider.GetData();
Console.ReadLine();
}
}
}
This is the only solution I could come up with for your problem:
interface IDataProvider
{
void GetData();
}
abstract class StandardDataProvider : IDataProvider
{
public virtual void GetData()
{
Console.WriteLine("GetData_StandardDataProvider");
}
}
class ManagedDataProvider : StandardDataProvider
{
public override void GetData()
{
Console.WriteLine("GetData_ManagedDataProvider");
}
public void GetBaseData()
{
base.GetData();
}
}
class Program
{
static void Main(string[] args)
{
IDataProvider dataprovider = new ManagedDataProvider();
dataprovider.GetData();
if (dataprovider is ManagedDataProvider)
{
(dataprovider as ManagedDataProvider).GetBaseData();
}
Console.ReadLine();
}
}
Another Way to attack it is adding GetBaseData to the Interface.
interface IDataProvider
{
void GetData();
void GetBaseData();
}
abstract class StandardDataProvider : IDataProvider
{
public virtual void GetData()
{
Console.WriteLine("GetData_StandardDataProvider");
}
public virtual void GetBaseData()
{
Console.WriteLine("GetData_StandardDataProvider");
}
}
class ManagedDataProvider : StandardDataProvider
{
public override void GetData()
{
Console.WriteLine("GetData_ManagedDataProvider");
}
public override void GetBaseData()
{
base.GetData();
}
}
class Program
{
static void Main(string[] args)
{
IDataProvider dataprovider = new ManagedDataProvider();
dataprovider.GetData();
dataprovider.GetBaseData();
Console.ReadLine();
}
}
I have a parent class that is firing an event to derived classes. The problem is that the event handler is alway null.
Class Plugin()
{
public delegate void BufferReadyHandler(string str);
public event BufferReadyHandler OnBufferReady;
public ClassPlugin(eGuiType _guyType)
{
GuiType = _guyType;
}
protected void Sp_DataReceived_Parent(object sender, SerialDataReceivedEventArgs e)
{
strCommonBuffer += serial.ReadExisting();
if (strCommonBuffer.Contains("\r\n"))
{
if (OnBufferReady != null) <<-------NULL
OnBufferReady(strCommonBuffer);
strCommonBuffer = string.Empty;
}
}
}
then there are some derived classes that are linked to that event:
class ClassIO : ClassPlugin
{
public ClassIO(eGuiType _guyType) : base(_guyType)
{
...
OnBufferReady += ClassIO_OnBufferReady;
}
private void ClassIO_OnBufferReady(string str)
{
...
}
}
the problem is that the OnBufferReady event in the parent class is alway null and therefore never fired.
Thanks for any help.
I might be wrong but have you thought about making the event static?
public delegate void BufferReadyHandler(string str);
public static event BufferReadyHandler OnBufferReady;
I am not sure why you are having this problem, I suspect it has something to do with the code you have not shown us. However in this situation I would not have the child subscribe to the event at all, instead make a protected method that raises the event that the child can override.
Here is how I would implement the class.
public class BufferReadyEventArgs : EventArgs
{
public BufferReadyEventArgs(string commonBuffer)
{
CommonBuffer = commonBuffer;
}
public string CommonBuffer {get; private set;}
}
Class Plugin()
{
public event EventHandler<BufferReadyEventArgs> OnBufferReady;
public ClassPlugin(eGuiType _guyType)
{
GuiType = _guyType;
}
protected void Sp_DataReceived_Parent(object sender, SerialDataReceivedEventArgs e)
{
strCommonBuffer += serial.ReadExisting();
if (strCommonBuffer.Contains("\r\n"))
{
RaiseOnBufferReady(strCommonBuffer);
strCommonBuffer = string.Empty;
}
}
protected virtual void RaiseOnBufferReady(string commonBuffer)
{
var temp = OnBufferReady;
if(temp != null)
temp(this, new BufferReadyEventArgs(commonBuffer));
}
}
class ClassIO : ClassPlugin
{
public ClassIO(eGuiType _guyType) : base(_guyType)
{
...
}
protected override void RaiseOnBufferReady(string commonBuffer)
{
base.RaiseOnBufferReady(commonBuffer);
...
}
}
Here is a working example based on your code:
using System;
using System.Collections.Generic;
public class MyClass
{
public static void Main()
{
ClassIO c = new ClassIO();
c.DataReceived();
Console.ReadLine();
}
}
public class ClassPlugin
{
public delegate void BufferReadyHandler(string str);
public event BufferReadyHandler OnBufferReady;
public ClassPlugin()
{
}
public void DataReceived()
{
if (OnBufferReady != null) {
OnBufferReady("Calling OnBufferReady");
}
}
}
public class ClassIO : ClassPlugin
{
public ClassIO() : base()
{
OnBufferReady += ClassIO_OnBufferReady;
}
private void ClassIO_OnBufferReady(string str)
{
Console.WriteLine("Inside ClassIO_OnBufferReady");
}
}
I don't understand why you would like to work with events in the first place for communication between parent and derived class.
If you need this communication, you would be better of with an (abstract) method in your base class that you implement in your derived classes.
If you need communication to all instances of derived types, you should look into composition instead of inheritance. Make some sort of manager instance that holds references to a list of instances of that base type and invokes a certain method on each of them in case of an 'event'.
I'm trying to create my own state machine but ran into some trouble regarding lists of classes with generic type. My code is as below.
State.cs:
using UnityEngine;
using System.Collections;
public abstract class State<T> where T:StateMachine
{
public T sm;
public State()
{
}
public virtual void OnEnter()
{
sm.currentState = sm.futureState;
}
public abstract void OnExit();
public abstract void OnLoop();
}
StateMachine.cs:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public abstract class StateMachine : MonoBehaviour
{
public List<State<T>> stateList = new List<T>>();
public int currentState = -1;
public int futureState;
protected virtual void Start()
{
foreach (State<T> s in stateList)
{
s.sm = this;
}
}
protected virtual void Update()
{
if (currentState != futureState)
{
stateList[futureState].OnEnter();
}
stateList[currentState].OnLoop();
if (currentState != futureState)
{
stateList[currentState].OnExit();
}
}
}
TestStateMachine.cs:
using UnityEngine;
using System.Collections;
public class TestStateMachine : StateMachine
{
public enum StateNames:int
{
State1,
State2,
};
public KeyCode kc;
// Use this for initialization
protected override void Start ()
{
stateList.Add(new TestStateMachineFirstState());
stateList.Add(new TestStateMachineSecondState());
base.Start();
}
}
public class TestStateMachineFirstState : State<StateMachine>
{
public override void OnEnter()
{
Debug.Log("SM1 OnEnter");
base.OnEnter();
}
public override void OnLoop()
{
Debug.Log("SM1 OnLoop");
if (Input.GetKeyDown(sm.kc))
{
sm.futureState = (int)TestStateMachine.StateNames.State2;
}
}
public override void OnExit()
{
Debug.Log("SM1 OnExit");
}
}
public class TestStateMachineSecondState : State<StateMachine>
{
public override void OnEnter()
{
Debug.Log("SM2 OnEnter");
base.OnEnter();
}
public override void OnLoop()
{
Debug.Log("SM2 OnLoop");
if (Input.GetKeyDown(sm.kc))
{
sm.futureState = (int)TestStateMachine.StateNames.State1;
}
}
public override void OnExit()
{
Debug.Log("SM2 OnExit");
}
}
I get error CS0246: Type or namespace name T cannot be found (or something that sounds similar).
My state machine "functions" if I replace all State<T> and State<TestStateMachine> with State<StateMachine> and the if (Input.GetKeyDown(sm.kc)) with (Input.GetKeyDown(KeyCode.A)).
But that is not ideal as I would not be able to get variables from the children state machines. Is there a way to keep this structure(as bad as it might be), or should I try another approach in doing state machines?
One might note that if you look at the compiler error message, it will specify the source file and the line number at which the error was detected. That usually helps identify the problem.
The problem is this:
public abstract class StateMachine : MonoBehaviour
{
public List<State<T>> stateList = new List<T>>();
...
T has no meaning in this class as it's not an generic class or method. Hence, the compiler has no idea what to do with State<T> or List<T.
A second problem is that
public List<State<T>> stateList = new List<T>>();
wouldn't compile even if in a suitable generic class or method: List<State<T>> is not a compatible type with List<T>.
The reason you get this compilation error is because you are using type parameter T of type State in the StateMachine class. You could employ the curiously recurring template pattern:
class State<T> where T : StateMachine
class StateMachine<T> where T : StateMachine
class RealStateMachine : StateMachine<RealStateMachine>
However, this might be very confusing. If you are able, you should consider a design where State is a nongeneric abstract class or interface.
Error in line : public virtual void BuyFavoriteStuff()
Error : Expected class, delegate, enm, interface, or struct
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LearnAbstractClass
{
class Program
{
static void Main(string[] args)
{
}
}
class Shopper
{
private int TotalSpent=0, CreditLimit=10;
public void ShopTillYouDrop()
{
while (TotalSpent < CreditLimit)
BuyFavoriteStuff();
}
}
public virtual void BuyFavoriteStuff()
{
// No implementation here - we don’t know
// what our student likes to buy!
}
class ArtStudent : Shopper
{
public override void BuyFavoriteStuff()
{
BuyArtSupplies();
BuyBlackTurtlenecks();
BuyDepressingMusic();
}
private void BuyBlackTurtlenecks()
{}
private void BuyDepressingMusic()
{}
private void BuyArtSupplies()
{}
}
class EngineeringStudent : Shopper
{
public override void BuyFavoriteStuff()
{
BuyPencils();
BuyGraphingCalculator();
BuyPocketProtector();
}
private void BuyPencils()
{}
private void BuyGraphingCalculator()
{}
private void BuyPocketProtector()
{}
}
}
What is the wrong in implementation above?
your method:
public virtual void BuyFavoriteStuff()
{
// No implementation here - we don’t know
// what our student likes to buy!
}
it outside of the Shopper class
You have method that is outside of any class:
public virtual void BuyFavoriteStuff()
{
// No implementation here - we don’t know
// what our student likes to buy!
}
just move it to Shopper class.
The method BuyFavoriteStuff is not inside class
public virtual void BuyFavoriteStuff()
{
// No implementation here - we don’t know
// what our student likes to buy!
}
You should declare your method inside class.
I seem to have a problem in C# with constructors, inheritance and event subscription.
Consider the following C# program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace EventTest
{
public class Widget
{
public delegate void MyEvent();
public event MyEvent myEvent;
public void SetEvent()
{
myEvent();
}
}
public class Base
{
Widget myWidget;
protected Base() { }
protected Base(Widget awidget)
{
myWidget = awidget;
myWidget.myEvent += myEvent;
}
public void myEvent() { }
}
public class Derived : Base
{
public Derived(Widget awidget) : base(awidget) { }
new public void myEvent()
{
System.Console.WriteLine("The event was fired, and this text is the response!");
}
}
class Program
{
static void Main(string[] args)
{
Widget myWidget = new Widget();
Derived myDerived = new Derived(myWidget);
myWidget.SetEvent();
}
}
}
What I want is for the text to be displayed. i.e. I want to subscribe an inherited base method to an event in base class, then be able to call the constructor in a subclass, and get the subclasses' event method to get called instead of the base classes' when that event is fired.
Is there any way to do this?
You need to set the method virtual :
public class Base
{...
public virtual void myEvent() { }
And override it
public class Derived : Base
{
...
public override void myEvent()
{
System.Console.WriteLine("The event was fired, and this text is the response!");
}
}
new public void myEvent()
This creates a new event. You don't want that. Make the event virtual in the base class and use override instead of new here.
Mark the base class method as virtual and your problem will be solved.
public virtual void myEvent() { }