public abstract class State<T>
{
public virtual Enter(T item)
{
// an empty method
}
}
public class ChaseState : State<FieldPlayer>
{
public override Enter(Player pl)
{
// ...
pl.Fsm.CurrentState = ChaseState.Instance;
//...
}
}
public class TendGoal : State<Goalkeeper>
{
public override Enter(Goalkeeper gk)
{
// ...implementation
gk.Fsm.CurrentState = TendGoal.Instance;
// ...implementation
}
}
public class DefendState : State<Team>
{
public override Enter(Team team)
{
// ....
team.Fsm.CurrentState = DefendState.Instance;
//.....
}
}
"Goalkeeper" and "FieldPlayer" inherit from an abstract class "Player", while "Team" inherits from another class.
public class FSM
{
public /*some type*/ owner; // PROBLEM 1
// OWNER CAN BE TEAM, GOALKEEPEEPER
// OR FIELD PLAYER
public /*some type*/ globalState;
public /*some type*/ currentState;
public /*some type*/ previousState;
public void Update()
{
if (globalState != null)
{
globalState.Execute(owner); // PROBLEM 2
// IF GLOBAL STATE'S TYPE
// IS AN OBJECT, CANT CALL EXECUTE
// OBJECTS TYPE WILL BE KNOWN ONLY
// DURING RUNTIME
}
}
}
Each object of type "Goalkeeper", "FieldPlayer" and "Team" will have a State Machine instance. The problem is.. generics cant be properties.
What should I do ?
If you make State an ordinary interface, not generic, and have its Enter method take another interface that your teams, goalkeeprs, players, etc all implement (it can even just be empty), it ought to work.
public interface IOwner {}
public interface IState
{
void Enter(IOwner item);
}
public class ChaseState : IState
{
public void Enter(IOwner pl)
{
// ...
//...
}
}
public class Player :IOwner { }
public class Something {
IOwner owner = new Team();
IState globalState = new ChaseState();
IState currentState = new DefendState();
public void Update()
{
if (globalState != null)
{
globalState.Enter(owner);
}
else if (currentState != null)
{
currentState.Enter(owner);
}
}
}
After reading your code some more, an Abstract Class is unnecessary here. You should convert State to an interface, ex: IState and remove the generic signature from it. Then your properties in your FSM object can all be public IState globalState, etc..
Related
I'm creating an abstract finite machine state class with an enum for the possible commands it can receive, something like:
public abstract class FSMBase
{
public enum Commands {};
public enum States;
public Dictionary<Transition, States> AvailableTransitions;
public States CurrentState;
public abstract void InitCommandsAndStatesAndTransitiosnAndInitialState();
public void ProcessCommand(Commands _command)
{
Transition RequestedTransition = new Transition(CurrentState, command);
if(AvailableTransitions.TryGetValue(RequestedTransition, out State nextState) //pseudocode
{
CurrentState = nextState;
}
}
}
Then in the derived class I would like to override the States, the Transitions and the Commands. Something like:
public class MyFSM : FSMBase
{
public override void InitCommandsAndStatesAndTransitiosnAndInitialState()
{
States = {Off, starting, started, ...} //HERE IS MY PROBLEM
Commands = {start, stop, finish, ...}; // HERE IS MY PROBLEM
Transitions = new Dictionary<Transition, BaseState>
{
{new Transition(States.Off, Commands.Start), States.starting},
....
}
CurrentState = States.Off;
}
}
How do I override the enums in my derived class ???
Well, enum is in fact int (byte, short, long ect.) and can't be overriden. I suggest using generics instead
public abstract class FSMBase<State, Command>
where State : Enum // : Enum wants C# 7.3+
where Command : Enum {
//TODO: I suggest have these fields private, or at least, protected
public Dictionary<Transition, State> AvailableTransitions;
public State CurrentState;
public void ProcessCommand(Command _command) {
...
}
}
When implementing MyFSM you can put required enums:
public class MyFSM : FSMBase<MyStates, MyCommands> {
...
}
Edit: in case of lower c# versions you can try same idea but different constraints:
public abstract class FSMBase<State, Command>
where State : struct
where Command : struct {
public State CurrentState;
...
// Instead of compile time error we are going to have runtime one,
// if either State or Command is not enum
static FSMBase() {
if (!typeof(State).IsEnum)
throw new InvalidCastException("Generic pararameter State must be enum!");
else if (!typeof(Command).IsEnum)
throw new InvalidCastException("Generic pararameter Command must be enum!");
}
}
...
public class MyFSM : FSMBase<MyStates, MyCommands> {
public override void InitCommandsAndStatesAndTransitiosnAndInitialState() {
...
CurrentState = MyStates.Off;
...
}
...
}
is this possible to somehow, have this scenario, where A.N inherits code from A with this code example?
The reason for setting it up like this, is that I need multiple classes that inherit from Base<TType> and the Nested : Base<TType> where the server has the base only, and the client has the extended Nested. This way, it would be easy to use the code, where they would have some shared code between themselves & each other.
The problem is that I would have to write identical code inside the
A and A.N
B and B.N
C and C.N
etc.
I have solved this temporarily, by replacing the Nested abstract class, with an Interface and doing
A.N : A, INested, but now I have to rewrite the Base<TType>.Nested code again inside all the Nested classes. For now, the nested class is small & managable.
hope this isn't a confusing question...
public abstract class Base<TType> where TType : class
{
public TType data;
internal void CommonCodeForAll() { }
public abstract void Update();
public abstract class Nested : Base<TType>
{
public abstract void Input();
}
}
public class A : Base<someClass>
{
public float Somevariable;
public void SpecificFunctionToA() { }
public override void Update()
{
// code that gets executed on server & client side that is unique to A
}
public class N : A.Nested
{
public override void Input()
{
if (data.IsReady()) { Somevariable *= 2; }
SpecificFunctionToA();
}
}
}
public class B : Base<anotherClass>
{
public float Somevariable;
public int index;
public int[] Grid;
public void SomethingElse() { }
public override void Update()
{
// code that gets executed on server & client side that is unique to B
}
public class N : B.Nested
{
public override void Input()
{
if (Grid[index] == -1) { SomethingElse(); }
data.Somevariable = Grid[index];
}
}
}
Edit:
I updated the code example to show what I'm trying to achieve.
Why I am trying to do this, is to keep the physics, networking & User input seperate.
There are multiple different controllers where each one has their own pack & unpacking functions, controller identity & access to the physics engine.
I have a solution using ecapsulation of classes instead of inheritance.
public abstract class BaseGeneric<T>
{
T data;
// ctor
protected BaseGeneric(T data)
{
this.data=data;
}
// methods
public abstract void Update();
// properties
public T Data
{
get { return data; }
set { data=value; }
}
// base nested class
public abstract class BaseNested<B> where B : BaseGeneric<T>
{
protected B #base;
// ctor
protected BaseNested(B #base)
{
this.#base=#base;
}
// methods
public abstract void Input(T data);
public void Update() { #base.Update(); }
// properties
public T Data
{
get { return #base.data; }
set { #base.data=value; }
}
}
}
// implementation base
public class Base : BaseGeneric<int>
{
// ctor
protected Base(int data) : base(data) { }
//methods
public override void Update()
{
this.Data+=1;
}
// implemented nested class
public class Nested : Base.BaseNested<Base>
{
// ctor
public Nested(int data) : base(new Base(data)) { }
public Nested(Base #base) : base(#base) { }
// methods
public override void Input(int data)
{
this.Data=data;
}
}
}
class Program
{
static void Main(string[] args)
{
// new implemented class with value 0
var nested=new Base.Nested(0);
// set value to 100
nested.Input(100);
// call update as implemented by `Base`.
nested.Update();
}
}
I have used delegates to represent methods - but I now have many classes that have same methods (but different code in those methods).
Is there a way to delegate the entire class?
Pseudo code:
class myModelA
{
void update()
{
}
}
class myModelB
{
void update()
{
}
}
delegate class myModel;
if (x==1)
myModel = myModelA;
else
myModel = myModelB;
myModel.update();
I know I can delegate the "üpdate" method BUT in real world I have lots of methods and I would rather just simply delegate the class.
EDIT1 based on Jon Skeet's answer
BUT how do I declare a public variable? (non public variables compile OK)
public interface IModel
{
double myDouble; <<<< this gives an error
void Update();
}
public class MyModelA : IModel
{
public double myDouble;
public void Update() { ... }
}
public class MyModelB : IModel
{
public double myDouble;
public void Update() { ... }
}
No, in this case you don't want a delegate - you want an interface.
You create an interface which all of your classes implement:
public interface IModel
{
void Update();
}
public class MyModelA : IModel
{
public void Update() { ... }
}
public class MyModelB : IModel
{
public void Update() { ... }
}
Then:
IModel model;
if (x == 1)
{
model = new MyModelA();
}
else
{
model = new MyModelB();
}
model.Update();
As Jon Skeet, I think you need to use interfaces.
A little changed code from
http://www.dotnetperls.com/interface
using System;
interface IPerl
{
void Read();
}
class TestA : IPerl
{
public void Read()
{
Console.WriteLine("Read TestA");
}
}
class TestB : IPerl
{
public void Read()
{
Console.WriteLine("Read TestB");
}
}
class Program
{
static void Main()
{
IPerl perl = new TestA(); // Create instance.
perl.Read(); // Call method on interface.
}
}
I'm trying to use Polymorphism to have a derived class operate with a derived property instead of the base property. I'm not sure how to put it in clearer words, so here's an example with the output:
// setup output to demonstrate the scenario
static void Main(string[] args)
{
var foo = new Foo();
var foobase = foo as FooBase;
Console.WriteLine("Foo is null? {0}", foo == null);
Console.WriteLine("Foo.Bar is null? {0}", foo.Bar == null);
Console.WriteLine("FooBase is null? {0}", foobase == null);
Console.WriteLine("FooBase.Bar is null? {0}", foobase.Bar == null);
Console.ReadLine();
}
// base and derived. These represent my problem.
class BarBase { }
class Bar : BarBase { }
// Base implementation using base properties
class FooBase
{
public virtual BarBase Bar { get; set; }
public FooBase() { }
}
// Derived implementation using "new" to operate with the
// derived the property
class Foo : FooBase
{
public new Bar Bar { get; set; }
public Foo() : base()
{
// populate our modified property with the derived class
Bar = new Bar();
//base.Bar = Bar; // I don't want to do this, but how can I avoid it?
}
}
OUTPUT:
Foo is null? False
Foo.Bar is null? False
FooBase is null? False
FooBase.Bar is null? True
The problem is "FooBase.Bar" is NULL. I understand that the new modifier is hiding the base implementation, that's why I know I can make it work by adding the (commented out) line:
base.Bar = Bar; // I don't want to do this, but how can I avoid it?
Is there a better way? What am I missing?
Thanks in advance!
EDIT (6/7/11)
Adding a more specific example to my problem. Basically, there are abstract implementations for a Game and a Camera (very basic here...). The abstract Game uses the abstract Camera for basic work. The derived Game uses its derived Camera for its specialty work. In the end, I'd need both the derived and the abstract Cameras to work in their own scope.
I've given two different Camera implementations and two Game implementations to (hopefully) demonstrate the flexibility I'm looking for. Please note that Game1 uses a "hack" to force the base Camera to have a value- Game2 does not do this. Game1 has the behavior I want, but not the implementation I want.
class GameAndCameraExample
{
static void Main(string[] args)
{
new Game1().Play();
Console.WriteLine();
new Game2().Play();
Console.ReadLine();
}
// abstract camera
abstract class CameraBase
{
public void SpecialCameraBaseMethod()
{
Console.WriteLine("SpecialCameraBaseMethod");
}
}
// camera implementation
class ChaseCamera : CameraBase
{
public void SpecialChaseCameraMethod()
{
Console.WriteLine("SpecialChaseCameraMethod");
}
}
// a different camera implementation
class FlightCamera : CameraBase
{
public void SpecialFlightCameraMethod()
{
Console.WriteLine("SpecialFlightCameraMethod");
}
}
// abstract game
abstract class GameBase
{
public virtual CameraBase Camera { get; set; }
public GameBase() { }
public virtual void Play()
{
Console.WriteLine("GameBase.Camera is null? {0}", Camera == null);
if(Camera != null) // it will be null for Game2 :-(
Camera.SpecialCameraBaseMethod();
}
}
// awesome game using chase cameras
class Game1 : GameBase
{
public new ChaseCamera Camera { get; set; }
public Game1() : base()
{
Camera = new ChaseCamera();
base.Camera = Camera; // HACK: How can I avoid this?
}
public override void Play()
{
Console.WriteLine("Game.Camera is null? {0}", Camera == null);
Camera.SpecialChaseCameraMethod();
base.Play();
}
}
// even more awesome game using flight cameras
class Game2 : GameBase
{
public new FlightCamera Camera { get; set; }
public Game2()
: base()
{
Camera = new FlightCamera();
}
public override void Play()
{
Console.WriteLine("Game.Camera is null? {0}", Camera == null);
Camera.SpecialFlightCameraMethod();
base.Play();
}
}
}
OUTPUT:
Game.Camera is null? False
SpecialChaseCameraMethod
GameBase.Camera is null? False
SpecialCameraBaseMethod
Game.Camera is null? False
SpecialFlightCameraMethod
GameBase.Camera is null? True
Is inheritance even the best approach for this?
You need to use override instead of new.
You can still return a Bar object, thought it will still return as BarBase. But override is the only way to make sure that Foo's property is used instead of FooBase's property when the Foo object is cast as FooBase.
Generics could help in this situation, mainly on the FooBase class:
class FooBase<T> where T: BarBase {
public virtual T Bar { get; set; }
public FooBase() { }
}
class Foo : FooBase<Bar> {
public override Bar Bar { get; set; }
public Foo() : base() {
Bar = new Bar();
}
}
And here's the modifications to Main():
static void Main( string[] args ) {
var foo = new Foo();
var foobase = foo as FooBase<Bar>;
Console.WriteLine( "Foo is null? {0}", foo == null );
Console.WriteLine( "Foo.Bar is null? {0}", foo.Bar == null );
Console.WriteLine( "FooBase is null? {0}", foobase == null );
Console.WriteLine( "FooBase.Bar is null? {0}", foobase.Bar == null );
Console.ReadKey();
}
The constraint of generic parameter T to BarBase means any subclass of FooBase can opt-in to any subclass of BarBase, or just deal with BarBase:
class VagueFoo : FooBase<BarBase> { }
I'm going to present an answer to my own question. Actually, two answers. There are likely many other answers but none are finding their way here.
Solution #1: Parallel Hierarchies
This idea was brought up by #Joel B Fant in an earlier comment. I looked over how ADO.NET is implemented (via Reflector) to come up with an implementation. I'm not thrilled about this pattern because it means multiple properties for the same family of objects- but it is a reasonable solution.
(Let's assume that the CameraBase, FlightCamera, and ChaseCamera from my question are still defined to save space)
CODE
// abstract game
abstract class GameBase
{
public virtual CameraBase CameraBase { get; set; }
public GameBase() { }
public virtual void Play()
{
Console.WriteLine("GameBase.CameraBase is null? {0}", CameraBase == null);
if (CameraBase != null)
CameraBase.SpecialCameraBaseMethod();
}
}
// awesome game using chase cameras
class Game1 : GameBase
{
public override CameraBase CameraBase
{
get { return Camera; }
set { Camera = (ChaseCamera)value; }
}
public ChaseCamera Camera { get; set; }
public Game1()
{
Camera = new ChaseCamera();
}
public override void Play()
{
Console.WriteLine("Game.Camera is null? {0}", Camera == null);
Camera.SpecialChaseCameraMethod();
base.Play();
}
}
Solution #2: Inheritance, Injection, and a Twist
This "pattern" might have a real name, but I don't know it. It's very similar to Parallel Hierarchies (as well as my original example) except I'm injecting the camera through the constructor and using the base properties (with casting) for access. I suppose I could have avoided the injection and do a straight assignment to the base property as well (but why avoid injection? It's so useful!). The twist is simply the required casting for the properties. It's not clean, but it's not ugly either. This is my current preferred solution.
CODE
// must inject the camera for this solution
static void Main(string[] args)
{
new Game1(new ChaseCamera()).Play();
Console.ReadLine();
}
// abstract game
abstract class GameBase
{
public virtual CameraBase Camera { get; set; }
public GameBase(CameraBase camera) // injection
{
Camera = camera;
}
public virtual void Play()
{
Console.WriteLine("GameBase.Camera is null? {0}", Camera == null);
if (Camera != null)
Camera.SpecialCameraBaseMethod();
}
}
// awesome game using chase cameras
class Game1 : GameBase
{
public new ChaseCamera Camera
{
get { return (ChaseCamera)base.Camera; }
set { base.Camera = value; }
}
public Game1(ChaseCamera camera) : base(camera) { } // injection
public override void Play()
{
Console.WriteLine("Game.Camera is null? {0}", Camera == null);
Camera.SpecialChaseCameraMethod();
base.Play();
}
}
Both of these solutions give me the desired results with an acceptable implementation.
class Foo : FooBase
{
public override BarBase Bar { get; set; }
public Foo() : base()
{
// populate our modified property with the derived class
Bar = new Bar();
//base.Bar = Bar; // I don't want to do this, but how can I avoid it?
}
}
You may try this: change Property type to BarBase and use override. Then use polimorphism to assign a derived class Bar object to the BarBase Property. Property Bar is virtual so the right object will be returned.
Heres a tip for solution:
class GameAndCameraExample
{
static void Main(string[] args)
{
new Game1().Play();
Console.WriteLine();
new Game2().Play();
Console.ReadLine();
}
// abstract camera
abstract class CameraBase
{
public void SpecialCameraBaseMethod()
{
Console.WriteLine("SpecialCameraBaseMethod");
}
}
// camera implementation
class ChaseCamera : CameraBase
{
public void SpecialChaseCameraMethod()
{
Console.WriteLine("SpecialChaseCameraMethod");
}
}
// a different camera implementation
class FlightCamera : CameraBase
{
public void SpecialFlightCameraMethod()
{
Console.WriteLine("SpecialFlightCameraMethod");
}
}
// abstract game
abstract class GameBase<T> where T : CameraBase, new()
{
public T Camera { get; set; }
public GameBase()
{
Camera = new T();
}
public virtual void Play()
{
Console.WriteLine("GameBase.Camera is null? {0}", Camera == null);
if (Camera != null) // it will be null for Game2 :-(
Camera.SpecialCameraBaseMethod();
}
}
// awesome game using chase cameras
class Game1 : GameBase<ChaseCamera>
{
public override void Play()
{
Console.WriteLine("Game.Camera is null? {0}", Camera == null);
Camera.SpecialChaseCameraMethod();
base.Play();
}
}
// even more awesome game using flight cameras
class Game2 : GameBase<FlightCamera>
{
public override void Play()
{
Console.WriteLine("Game.Camera is null? {0}", Camera == null);
Camera.SpecialFlightCameraMethod();
base.Play();
}
}
}
Hope you find this useful.
-Zsolt
I'm trying out an example of using Domain Events to notify of when something has happened in a system (borrowed from here and here).
I'm really close to getting the code working how I want, however, I've hit a bit of a brick wall. Here is my DomainEvents class:
public static class DomainEvents
{
[ThreadStatic]
private static IList<IEventHandler<IDomainEvent>> Actions;
public static void Register<T>(IEventHandler<T> callback) where T : IDomainEvent
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback); // <---- Problem here, since I can't add callback to the collection.
}
public static void ClearCallbacks()
{
Actions = null;
}
public static void Raise<T>(T args) where T : IDomainEvent
{
if (Actions == null)
{
return;
}
foreach (var action in Actions)
{
if (action is IEventHandler<T>)
{
((IEventHandler<T>)action).Handle(args);
}
}
}
The above won't compile because Actions.Add cannot accept callback since it's a IEventHandler<T> type rather then a IEventHandler<IDomainEvent> type. Here's some more code to clarify.
This is called from my console application:
DomainEvents.Register(new CustomerHasUnpaidDuesEventHandler());
CustomerHasUnpaidDuesEventHandler implements IEventHandler<CustomerHasUnpaidDuesEvent>, where CustomerHasUnpaidDuesEvent implements IDomainEvent.
public class CustomerHasUnpaidDuesEventHandler : IEventHandler<CustomerHasUnpaidDuesEvent>
{
public IEmailSender EmailSender { get; set; }
public void Handle(CustomerHasUnpaidDuesEvent #event)
{
this.EmailSender.SendEmail(#event.Customer.EmailAddress);
}
}
public class CustomerHasUnpaidDuesEvent : IDomainEvent
{
public CustomerHasUnpaidDuesEvent(Customer customer)
{
this.Customer = customer;
}
public Customer Customer { get; set; }
}
This is what I don't get - if CustomerHasUnpaidDuesEvent implements IDomainEvent, then why is the call to Actions.Add failing? How can I resolve this?
EDIT:
To make things clearer, here is entire code for my test app:
class Program
{
static void Main()
{
DomainEvents.Register(new CustomerHasUnpaidDuesEventHandler());
var c = new Customer();
c.EmailAddress = "test#dfsdf.com";
c.CheckUnpaidDues();
}
}
public interface IEventHandler<in T> where T : IDomainEvent
{
void Handle(T args);
}
public interface IEmailSender
{
void SendEmail(string emailAddress);
}
public interface IDomainEvent
{
}
public static class DomainEvents
{
[ThreadStatic]
private static IList<IEventHandler<IDomainEvent>> Actions;
public static void Register<T>(IEventHandler<T> callback) where T: IDomainEvent
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback);
}
public static void ClearCallbacks()
{
Actions = null;
}
public static void Raise<T>(T args) where T : IDomainEvent
{
if (Actions == null)
{
return;
}
foreach (IEventHandler<T> action in Actions)
{
(action).Handle(args);
}
}
}
public class CustomerHasUnpaidDuesEventHandler : IEventHandler<CustomerHasUnpaidDuesEvent>
{
public IEmailSender EmailSender { get; set; }
public void Handle(CustomerHasUnpaidDuesEvent #event)
{
this.EmailSender.SendEmail(#event.Customer.EmailAddress);
}
}
public class CustomerHasUnpaidDuesEvent : IDomainEvent
{
public CustomerHasUnpaidDuesEvent(Customer customer)
{
this.Customer = customer;
}
public Customer Customer { get; set; }
}
public class Customer
{
public string Name { get; set; }
public string EmailAddress { get; set; }
public bool HasUnpaidDues { get; set; }
public void CheckUnpaidDues()
{
HasUnpaidDues = true;
DomainEvents.Raise(new CustomerHasUnpaidDuesEvent(this));
}
}
Cheers.
Jas.
There is no need for your Register method to be generic:
public static void Register(IEventHandler<IDomainEvent> callback)
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback);
}
Edit:
The problem is that in order to have IEventHandler<CustomerHasUnpaidDuesEvent> to be in the list of IEventHandler<IDomainEvent>s, we need T to be a covariant template parameter in IEventHandler<T> (which is declared as IEventHandler<out T>). However in order to allow the function Handle(T arg), we need T to be contravariant. So strictly this way won't work. Imagine: if we really could insert an IEventHandler<CustomerHasUnpaidDuesEvent> into a list of IEventHandler<IDomainEvent>s, than someone might try to call Handle with the argument of some type which derives from IDomainEvent but is not a CustomerHasUnpaidDuesEvent! This should be impossible to do.
The solution is that we don't need the exact type at Register, so we can keep a reference to a generic base interface. The implementation is here: http://ideone.com/9glmQ
Old answer is not valid, kept below for consistency.
Maybe you need to declare IEventHandler to accept T as a covariant type?
interface IEventHandler<in T> where T: IDomainEvent
{
void Handle();
// ...
}
Edit: surely CustomerHasUnpaidDuesEvent is an IDomainEvent, but you need IEventHandler<CustomerHasUnpaidDuesEvent> to be a IEventHandler<IDomainEvent>. This is exactly what covariance does. In order to allow that, your template parameter in IEventhandler must be declared covariant (<in T> instead of just <T>).