I'm trying to implement a generic abstract method with a type constraint, then Implement it multiple times using different specified types.
public abstract class Ability
{
public abstract void BindToStation<T>(T station) where T : Station;
}
public class DashAbility : Ability
{
public override void BindToStation<NavStation>(NavStation station){ }
public override void BindToStation<CannonStation>(CannonStation station){ }
}
But I get an error which says the method has already been defined with the same paramater types.
I'm guessing that the compiler treats any generic paramater as the same in terms of the method signature, so these two methods look the same to it.
Still though, I'm wondering if theres a way to have generic method overloading using specific types.. ?
You can't do exactly what you want, but you can try an approach like this:
interface IBindableTo<T> where T : Station
{
void BindToStation(T station);
}
abstract class Ability
{
public abstract void BindToStation<T>(T station) where T : Station;
}
class DashAbility : Ability, IBindableTo<NavStation>, IBindableTo<CannonStation>
{
public override void BindToStation<T>(T station)
{
if (this is IBindableTo<T> binnder)
{
binnder.BindToStation(station);
return;
}
throw new NotSupportedException();
}
void IBindableTo<NavStation>.BindToStation(NavStation station)
{
...
}
void IBindableTo<CannonStation>.BindToStation(CannonStation station)
{
...
}
}
Hope this helps.
C# doesn't support specialization in that way, and neither does C++ easily when you want to specialize on runtime type.
But you can use polymorphism, so you can use double-dispatch:
public abstract class Station {
internal abstract void DashBindToStation();
}
public class NavStation : Station {
internal override void DashBindToStation() {
throw new NotImplementedException();
}
}
public class CannonStation : Station {
internal override void DashBindToStation() {
throw new NotImplementedException();
}
}
public abstract class Ability {
public abstract void BindToStation(Station station);
}
public class DashAbility : Ability {
public override void BindToStation(Station station) {
station.DashBindToStation();
}
}
Another possibility with C# is to use runtime dispatching using dynamic:
public abstract class Station {
}
public class NavStation : Station {
}
public class CannonStation : Station {
}
public abstract class Ability {
public abstract void BindToStation(Station station);
}
public class DashAbility : Ability {
public void BindToStation(NavStation station) {
}
public void BindToStation(CannonStation station) {
}
public override void BindToStation(Station station) {
BindToStation((dynamic)station);
}
}
Related
I create child objects (Customer, Product, ...) and invoke method ApplyChange in parent class (AggregateRoot), from that method I would like to call method Apply in child class for passed event. Is it possible using reflection or I should change something?
public abstract class AggregateRoot
{
public void ApplyChange(IEvent #event)
{
Apply(#event); // how to call this method?
}
}
public class Customer : AggregateRoot
{
private void Apply(CustomerCreatedEvent e)
{
Console.WriteLine("CustomerCreatedEvent");
}
}
public class Product : AggregateRoot
{
private void Apply(ProductCreatedEvent e)
{
Console.WriteLine("ProductCreatedEvent");
}
}
public interface IEvent
{
}
public class CustomerCreatedEvent : IEvent
{
}
public class ProductCreatedEvent : IEvent
{
}
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer();
customer.ApplyChange(new CustomerCreatedEvent());
Product product = new Product();
product.ApplyChange(new ProductCreatedEvent());
}
}
Is it possible using reflection or I should change something?
I focused for now on the non-reflection, as IMO reflection should be the last resort here.
Option 1: abstract method
You could make Apply an abstract method en then you could call it from AggregateRoot.
e.g.
using System;
public abstract class AggregateRoot
{
public void ApplyChange(IEvent #event)
{
Apply(#event); // how to call this method?
}
protected abstract void Apply(IEvent e);
}
public class Customer : AggregateRoot
{
protected override void Apply(IEvent e)
{
if (e is CustomerCreatedEvent)
{
Console.WriteLine("CustomerCreatedEvent");
}
}
}
public class Product : AggregateRoot
{
protected override void Apply(IEvent e)
{
if (e is ProductCreatedEvent)
{
Console.WriteLine("ProductCreatedEvent");
}
}
}
public interface IEvent
{
}
public class CustomerCreatedEvent : IEvent
{
}
public class ProductCreatedEvent : IEvent
{
}
But please note, it has it downsides as:
methods needs to non-private
the should have the same parameter type for Apply. (IEvent parameter) - so I've added the type check inside the Apply methods.
Option 2: abstract method and generic AggregateRoot
Another option is to make AggregateRoot generic for the type IEvent, e.g. something like this.
using System;
public abstract class AggregateRoot<TEvent>
where TEvent : IEvent
{
public void ApplyChange(TEvent #event)
{
Apply(#event); // how to call this method?
}
protected abstract void Apply(TEvent e);
}
public class Customer : AggregateRoot<CustomerCreatedEvent>
{
protected override void Apply(CustomerCreatedEvent e)
{
Console.WriteLine("CustomerCreatedEvent");
}
}
public class Product : AggregateRoot<ProductCreatedEvent>
{
protected override void Apply(ProductCreatedEvent e)
{
Console.WriteLine("ProductCreatedEvent");
}
}
public interface IEvent
{
}
public class CustomerCreatedEvent : IEvent
{
}
public class ProductCreatedEvent : IEvent
{
}
Note I've changed also ApplyChange in this case.
If those things won't solve your problem, please elaborate what you are trying to archive, otherwise this will be a XY problem
I want to reuse Cook method functionality, but still pass different parameters to execute:
public void Cook(BasicRequest request,IBaseInterface base)
{
// Some code
// More code
request.Execute(base);
}
public class BasicRequest
{
public abstract void Execute(IBaseInterface baseInterface)
}
public class RequestA : BasicRequest
{
public void Execute(IBaseInterface base)
{
var derived = (DerivedClassA)base;
// Do stuff with derived
}
}
public class RequestB : BasicRequest
{
public void Execute(IBaseInterface base)
{
var derived = (DerivedClassB)base;
// Do stuff with derived
}
}
public interface IDerivedClassA : IBaseInterface {}
public interface IDerivedClassB : IBaseInterface {}
I have a design issue here that casting is needed on each of requests execute methods.
How can I make this code cleaner ?
You should be using generics.
Update the BaseRequest to a generic class:
public abstract class BasicRequest<T> where T:IBaseInterface
{
public abstract void Execute(T baseInterface);
}
Change your class Cook method as follows:
public void Cook<T>(BasicRequest<T> request, T ibase) where T:IBaseInterface
{
// Some code
// More code
request.Execute(ibase);
}
Change your classes,
public class RequestA : BasicRequest<DerivedClassA>
{
public override void Execute(DerivedClassA ibase)
{
// Do stuff with derived
}
}
public class RequestB : BasicRequest<DerivedClassB>
{
public override void Execute(DerivedClassB ibase)
{
// Do stuff with derived
}
}
Hi everyone I am programming in Unity3d with C# and while I was writing my code I stumbled with a little issue, I write to you an example because I dont know explain me.
class Base
{
public string name;
}
class Derived : Base
{
public void Gun();
}
class BasePlayer
{
public Base x;
}
class SoldierPlayer : BasePlayer
{
}
The situation is this, I want to do something like that
SoldierPlayer.x.Gun();
But I don't know how do it
The real case is this
public class BasePlayerController : MonoBehaviour
{
public BasePlayerManager playerManager;
...
public class RobotPlayerController : BasePlayerController {
...
playerManager = gameObject.AddComponent<RobotPlayerManager>();
And I will use new methods
UPDATE 1
I did a example better, I want to do in Base Controller manager.user.energy and be treated as the next type RobotManager.RobotUser.energy
BaseController
BaseManager
BaseUser
class BaseController
{
BaseManager manager;
public virtual void Move(int x,int y)...
}
class BaseManager {
BaseUser user;
public virtual Pause(bool state);
}
class BaseUser {
int life
}
RobotController
RobotManager
RobotUser
class RobotController : BaseController
{
// manager as RobotManager?
public void Ray(int x,int y);
}
class RobotManager : BaseManager
{
// user as RobotUser?
}
class RobotUser : BaseUser
{
int energy;
}
UPDATE 2
I seek to do this
public Run()
{
RobotController rc = new RobotController();
rc.manager.energy;
}
You can't call SoldierPlayer.x.Gun(); because SoldierPlayer.x has type Base which has not method Gun(). OOP world and C# can provide you many solutions, your choose depends on your goals.
some of them (order by best practise):
1) Overriding Polymorphism. Add .Gun() method to Base class and implemend it in derived classes. For example
class Base
{
public string name;
public void virtual Gun()
{
Trace.Log("I'm base class, i can't do anything");
}
}
class Derived : Base
{
public override void Gun()
{
Consule.WriteLine("Hello i have gun");
}
}
class Derived2 : Base
{
public override void Gun()
{
Consule.WriteLine("Hello i have 2 guns");
}
}
2) Overloading Polymorphism In many source this method is mentioned like some kind of polymorphism AD-HOC
public void GunAction(Derived2 o)
{
o.Gun();
}
public void GunAction(Derived1 o)
{
o.Gun();
}
public void GunAction(Base o)
{
Trace.Log("I'm base class, i can't do anything");
}
3) is-cast
public void GunAction(Base o)
{
if(o is Derived1 )
o.Gun();
if(o is Derived2 )
o.Gun();
}
UPDATE 1 answering to your new requirements
class BaseController
{
public BaseManager manager;
...
class RobotController1 : BaseController
{
// manager as RobotManager? - no it is stil BaseManager
public void Ray(int x,int y);
}
class RobotController2 : BaseController
{
// manager as RobotManager? - yes. now it is RobotManager
public void Ray(int x,int y);
public RobotController2()
{
manager = new RobotManager();
}
}
public void Run()
{
var controller = new RobotController2();// you have RobotManager
controller.manager = new BaseManager();// it is again BaseManager
}
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();
}
}
Suppose you had such code:
public Base
{
abstract void Register();
}
public Registrator1: Base
{
override void Register()
{
//uses the current state of the object to populate the UI captions
}
}
public Registrator2: Base
{
override void Register()
{
//uses the current state of the object to populate the UI captions
}
}
But When you receive a new business rule asking you to write Registrator3 which actually registers based on some parameter and you change your code base to the next:
public Base
{
abstract void Register(externalParam);
}
public Registrator1: Base
{
override void Register(externalParam)
{
//uses the current state of the object to populate theUI
}
}
public Registrator2: Base
{
override void Register(externalParam)
{
//uses the current state of the object to populate the UI
}
}
public Registrator3: Base
{
override void Register(externalParam)
{
//uses a DDD - service passed in the params to populate the UI
}
}
But Registrator1 and Registrator2 do not need that param and the code becomes smelly. What are the ways to re-write this code?
You could use an object as a parameter here; which is commonly used in scenarios where the number of parameters can vary depending on the call being used.
struct RegistrationInfo
{
public static readonly RegistrationInfo Empty = new RegistrationInfo();
public string Username;
public string CustomerName;
public string Validity;
}
abstract class Base
{
public abstract void Register(RegistrationInfo info);
// If you want to retain the paramaterless call:
public void Register()
{
Register(RegistrationInfo.Empty);
}
}
class Registrar1 : Base
{
public override void Register(RegistrationInfo info)
{
if (info.Username == null) throw new ArgumentNullException("info.Username");
}
}
class Registrar2 : Base
{
public override void Register(RegistrationInfo info)
{
if (info.CustomerName == null) throw new ArgumentNullException("info.CustomerName");
}
}
This has the advantage that you don't need to change method parameters (which is breaking interface) each time a parameter is added. The usage also becomes somewhat self-documenting:
var r = new Registrar1();
r.Register(new RegistrationInfo(){ Username = "JimJoe" });
r.Register(RegistrationInfo.Empty);
It's like air freshener for this type of code smell, while it's still smelly; you can make it smell nicer.
Finally you can make the call-site cleaner by making it a params argument (this has a small amount of overhead); in all honesty though it is more smelly because it's a language hack. Finally you could improve it with generics:
class RegistrationInfo
{
}
class RegistrationInfo1 : RegistrationInfo
{
public string Arg;
}
class RegistrationInfo2 : RegistrationInfo
{
public int Arg;
}
interface IBase<in TRegistration>
where TRegistration : RegistrationInfo
{
void Register(TRegistration registration);
}
class Base : IBase<RegistrationInfo>
{
public void Register(RegistrationInfo registration)
{
}
}
class Registrar1 : IBase<RegistrationInfo1>
{
public void Register(RegistrationInfo1 arg)
{
}
}
class Registrar2 : IBase<RegistrationInfo2>
{
public void Register(RegistrationInfo2 arg)
{
}
}
Is it not possible to contain the logic for externalParam in Registrator3?
In other words, Registrator3 uses the param, then calls the unmodified parameterless base?
A lot really depends on where the logic belongs. If it is something intrinsic to the base, then put it in the base, and either overload the Register() function or supply a default value for the param so that sub classes don't need to provide it.
Assuming you want to reuse the registration logic from the base class, you could update the code as follows:
public class Base
{
public virtual void Register(object externalParam)
{
// base registration logic goes here
}
}
public class Registrator1: Base
{
public override void Register(object externalParam)
{
base.Register(null);
// custom registration logic goes here
}
}
public class Registrator2: Base
{
public override void Register(object externalParam)
{
base.Register(null);
// custom registration logic goes here
}
}
public class Registrator3: Base
{
public override void Register(object externalParam)
{
base.Register(externalParam);
// custom registration logic goes here
}
}
HTH,
Cosmin
EDIT: Updated code to compile.