I'm working on a project that needs to replace concrete class with Interface. Below is the concrete class and its inheritance class
public class CarRepository
{
private string _model;
private string _colour;
public CarRepository(string model, string colour) {
_model = model;
_colour = colour
}
public string Get(GUID id)
{
return id.ToString();
}
protected virtual void DoSomething(ref ISpecial special) {
special = special.AddFields(Rego, ModelNumber)
}
}
public class BigCarRepository : CarRepository
{
public class BigCarRepository(string model, string colour)
: base(model, colour)
protected override void DoSomething(ref ISpecial special) {
special = special.AddFields(SpecialOffer, OptionPack)
}
}
I want to replace the inheritance of a concrete class for BigCarRepository from CarRepository with an interface (i.e. ICarRepository). Thus I created an interface and replacing the concrete class but couldn't find a way to address the override method. I have created the interface below and modified my concrete classes and the inheritance but stuck at the override method.
public interface ICarRepository
{
string Get(string id);
}
public class CarRepository : ICarRepository
{
private string _model;
private string _colour;
public CarRepository(string model, string colour) {
_model = model;
_colour = colour
}
public string Get(GUID id)
{
return id.ToString();
}
protected virtual void DoSomething(ref ISpecial special) {
special = special.AddFields(Rego, ModelNumber)
}
}
public class BigCarRepository : ICarRepository
{
public ICarRepository _carRepository { get; set; }
public BigCarRepository(ICarRepository carRepository)
{
_carRepository = carRepository;
}
public string Get (string id)
{
return _carRepository.Get(id);
}
**protected override void DoSomething(ref ISpecial special) {
special = special.AddFields(SpecialOffer, OptionPack)
}**
}
Update:
If you need to make an abstraction of CarRepository. You did well by extracting the interface. You also need to add all methods that you want your derived classes to implement.
public interface ICarRepository
{
string Get(string id);
void DoSomething(ref ISpecial special);
}
public class BigCarRepository : ICarRepository
{
public ICarRepository _carRepository { get; set; }
public BigCarRepository(ICarRepository carRepository)
{
_carRepository = carRepository;
}
public string Get (string id)
{
return _carRepository.Get(id);
}
public void DoSomething(ref ISpecial special) {
special = special.AddFields(SpecialOffer, OptionPack);
}
}
If this is what you want, you're fine.
In my previous answer, i suggested that you might need to reuse some logic of base class CarRepository , but still wanted to force BigCarRepository to implement his own logic of DoSomething. This could be usefull if you have the same code being reused in derived classes.
public abstract class CarRepository : ICarRepository
{
private string _model;
private string _colour;
protected CarRepository(string model, string colour) {
_model = model;
_colour = colour
}
public string Get(GUID id)
{
return id.ToString();
}
public absctract void DoSomething(ref ISpecial special); // Force all derived classes to implement this method
protected virtual void DoSomethingBase(ref ISpecial special) {
special = special.AddFields(Rego, ModelNumber)
}
}
public class BigCarRepository : CarRepository
{
public ICarRepository _carRepository { get; set; }
public BigCarRepository(ICarRepository carRepository) : base (pass_the_model, pass_the_colour)
{
_carRepository = carRepository;
}
public override void DoSomething(ref ISpecial special) {
DoSomethingBase(ref special); // if you need some base class logic
special = special.AddFields(SpecialOffer, OptionPack);
}
}
Related
I have interfaces and implementations like this:
public interface IRequest
{
string Name{set;get;}
}
public class UppercaseRequest: IRequest
{
public string Name{get; set}
}
public interface IHandler<T> where T: IRequest
{
void Handle(T request);
}
public class UpperCaseHandler : IHandler<UpperCaseRequest>
{
//implementation interface here
}
And a factory like this:
public class HandlerFactory
{
public IHandler<T> CreateHandler(T request) where T: IRequest
{
switch(request.Name)
{
case "UpperCase": return new UpperCaseHandler() as IHandler<T>;
//this line compile but always return null;
}
}
}
That handler method in HandlerFactory always returns null. What am I doing wrong and how can I fix this behavior? Can you also give me some advice on how I can improve the code structure?
Here is a modified and corrected code that works like a charm. We have the reference to an instance. But I don't know if it was you want...
The factory class should be static, isn't it ?
static void Test()
{
var a = new HandlerFactory().CreateHandler(new UpperCaseRequest() { Name = "UpperCase" });
}
public class HandlerFactory
{
public IHandler<T> CreateHandler<T>(T request) where T : IRequest
{
switch ( request.Name )
{
case "UpperCase": return new UpperCaseHandler() as IHandler<T>;
}
return default(IHandler<T>);
}
}
public interface IRequest
{
string Name { set; get; }
}
public class UpperCaseRequest : IRequest
{
public string Name { get; set; }
}
public interface IHandler<T> where T : IRequest
{
void Handle(T request);
}
public class UpperCaseHandler : IHandler<UpperCaseRequest>
{
public void Handle(UpperCaseRequest request)
{
throw new NotImplementedException();
}
}
I've been reading a lot about composition and trying to figure how I can refactor my inheritance tree using composition. Currently my class looks like this:
public abstract class BaseClass
{
public abstract string displayText { get; }
public abstract List<Parameter> parameters { get; }
public abstract void FireEvent();
}
public abstract class SubClass<T> : BaseClass
{
private string _displayText;
public override string displayText { get { return _displayText; } }
private List<Parameter> _parameters;
public override List<Parameter> parameters { get { return _parameters; } }
private T _value; // ADDED TO SUBCLASS
public abstract Event<T> Evt { get; } // ADDED TO SUBCLASS
public override void FireEvent()
{
Evt.Raise(_value);
}
}
public class IntClass : SubClass<int>{}
public class StringClass : SubClass<string>{} // more subclasses like this
From my understanding, there is both inheritance and composition going on here.
SubClass Has-A: (Composition)
List of Parameters
Field for Event
Behaviour of Event<T> which is called within it's own FireEvent method
SubClass Is-A: BaseClass (Inheritance)
IntClass/StringClass Is-A: SubClass & BaseClass
The reason for creating BaseClass is because I need polymorphic lists. This way I can create a List<BaseClass> and call FireEvent() on each element in the list and access the displayText and List<Parameter> in a loop.
In the future I will need a sub class which doesn't have an Event and a subclass which will accept a parameter in FireEvent(). Other variants might crop up.
How would I replace my current structure entirely with a composition based approach? Is it even doable?
In this example, you have 3 behaviors. Int uses 3, String uses only 2. If you put the code like this, when you change AnotherServiceB, you don't need to be worry about it break String (since String doesn't have that service)
public class FireEventService<T>
{
private T _value; // ADDED TO SUBCLASS
public abstract Event<T> Evt { get; } // ADDED TO SUBCLASS
public override void FireEvent()
{
Evt.Raise(_value);
}
}
public class AnotherService
{
}
public class AnotherServiceB
{
}
public abstract class SubClass<T> : BaseClass
{
private readonly FireEventService<T> _fireEventService;
private readonly AnotherService _anotherService;
private string _displayText;
public override string displayText { get { return _displayText; } }
private List<Parameter> _parameters;
public override List<Parameter> parameters { get { return _parameters; } }
public SubClass(FireEventService<T> fireEventService, AnotherService anotherService)
{
// All those services should use with interface and Dependency Injection
_fireEventService = fireEventService;
_anotherService = anotherService;
}
public void FireEvent() => _fireEventService.FireEvent();
}
public class IntClass : SubClass<int>
{
private readonly AnotherServiceB _anotherServiceB;
public IntClass(FireEventService<int> fireEventService, AnotherService anotherService, AnotherServiceB anotherServiceB)
: base(fireEventService, anotherService)
{ }
public void DoSomethingUsingServiceB()
{
//_anotherServiceB.DoSomething();
}
}
public class StringClass : SubClass<string>
{
public StringClass(FireEventService<string> fireEventService, AnotherService anotherService)
: base(fireEventService, anotherService)
{ }
}
I'm am just getting started with generics, and am confused by how to implement the following scenario.
This is my base class:
public abstract class UnclaimedProperty
{
public abstract string Key { get; }
public virtual void Process() { }
public virtual void Process(string FileName) { }
abstract public void WriteReport<T>(List<T> PropertyRecords, string FileName);
}
In my implementations I would like to pass a concrete list to the override. something like:
public class PennUnclaimed : UnclaimedProperty
{
public override void Process(string FileName)
{
var reportDollarRecords = new List<PennUnclaimed>();
//add items here
WriteReport(reportDollarRecords, "PennCash");
}
public override void WriteReport(List<UnclaimedProperty> PropertyRecords, string FileName)
{
//write report here
}
}
I get error:
'PennUnclaimed' does not implement inherited abstract member
'UnclaimedProperty.WriteReport<T>(List<T>, string)'
What would be the correct way to implement this?
Based on your comments, consider making the abstract class generic.
public abstract class UnclaimedProperty<T> where T : UnclaimedProperty<T> {
public abstract string Key { get; }
public virtual void Process() { }
public virtual void Process(string FileName) { }
abstract public void WriteReport(List<T> PropertyRecords, string FileName);
}
That way the implementation would look like this
public class PennUnclaimed : UnclaimedProperty<PennUnclaimed> {
public override void Process(string FileName) {
var reportDollarRecords = new List<PennUnclaimed>();
//add items here
WriteReport(reportDollarRecords, "PennCash");
}
public override void WriteReport(List<PennUnclaimed> PropertyRecords, string FileName) {
//write report here
}
public override string Key {
get {
return string.Empty; //TODO:return key
}
}
}
The constraint on the abstract class for the generic argument will allow it to be the type of the current class being implemented.
I ran into trouble when trying to create an abstract class and a method in it that was generic in nature.
class GameRoomManager : MonoBehaviour {
public GameRoom GetSomething(string s){
//do things here
return GameRoomvar;
}
}
Now I have another class that does something similar, but different classes involved
class PlayerManager : MonoBehaviour{
public Player GetSomething(string s){
//player related things here
return Playervar;
}
}
I want to have both classes GameRoomManager and PlayerManager inherit from an abstract class Abs
class GameRoomManager : Abs{
public override GameRoom GetSomething<GameRoom>(string s){
return GameRoomvar;
}
}
where
public abstract class Abs{
public T GetSomething<T>(string s);
}
I've seen a few answers on this topic when I was looking for solutions, and all suggested the abstract class itself be generic. I don't want to make the abstract class generic, since examples I saw would have me do class GameRoomManager : Abs<GameRoomManager>. But I want the method to return type GameRoom, not GameRoomManager.
I'm not totally familiar with generics, so please point me in the right direction if I'm going wrong
You have to have something in common with PQR and HIJ for the classes to use a common method.
Plan A
Connect things with interfaces.
public interface IPart
{
// put things here that are common between Part and GameRoom
int ID { get; }
}
public interface IAbs
{
IPart GetSomething(string name);
}
public class GameRoom : IPart
{
public int ID { get; set; }
}
public class GameRoomManager : IAbs
{
GameRoom part;
#region IAbs Members
public GameRoom GetSomething(string name)
{
return part;
}
IPart IAbs.GetSomething(string name)
{
return GetSomething(name);
}
#endregion
}
public class Player : IPart
{
public int ID { get; set; }
}
public class PlayerManager : IAbs
{
Player part;
#region IAbs Members
public Player GetSomething(string name)
{
return part;
}
IPart IAbs.GetSomething(string name)
{
return GetSomething(name);
}
#endregion
}
Plan B
Use a base class with a generic type & interfaces
public interface IItem
{
// put things here that are common between Part and GameRoom
int ID { get; }
}
public class GameRoom : IItem
{
public int ID { get; set; }
}
public class Player : IItem
{
public int ID { get; set; }
}
public interface IAbs
{
IItem GetItem(string guid);
}
public abstract class Abs<T> : IAbs
where T : IItem
{
protected abstract T GetItem(string name);
protected Abs(T item)
{
this.Item=item;
}
protected T Item { get; private set; }
#region IAbs Members
IItem IAbs.GetItem(string name)
{
return GetItem(name);
}
#endregion
}
public class GameRoomManager : Abs<GameRoom>
{
public GameRoomManager(GameRoom room) : base(room)
{
}
protected override GameRoom GetItem(string guid)
{
return Item;
}
public GameRoom GetRoom(string guid) { return GetItem(guid); }
}
public class PlayerManager : Abs<Player>
{
public PlayerManager(Player player)
: base(player)
{
}
protected override Player GetItem(string guid)
{
return Item;
}
public Player GetPlayer(string guid) { return GetItem(guid); }
}
here is some example usage:
class Program
{
static void Main(string[] args)
{
List<IAbs> managers=new List<IAbs>();
var pm=new PlayerManager(new Player() { ID=1001 });
var gm=new GameRoomManager(new GameRoom() { ID=2050 });
managers.Add(pm);
managers.Add(gm);
IItem part = managers[0].GetItem("0000");
}
}
Using interface inheritance, I would like to have all items from all ancestors in terminal interface/class and I also would like to have a base interface for all derived interfaces/objects (inheritance tree root) for general object processing like Process(IBase b). So, for example, instead of this:
public interface IBase
{
Guid Id {get;}
void SwitchOn();
}
public interface IPart1 : IBase {void DoPart1Specific();}
public interface IPart2 : IBase {void DoPart2Specific();}
public interface ICompound1 : IPart1, IPart2 {}
public class Compound : ICompound1
{
public Guid Id => Guid.Empty; // IBase
public void SwitchOn() {} // IBase
public void DoPart1Specific() {} // IPart1
public void DoPart2Specific() {} // IPart2
}
I would like to have something like this (using pseudo-explicit-interface-implementation notation which of course won't work here):
public class Compound : ICompound1
{
Guid Part1.Id => Guid.Empty; // ICompound1.IPart1
void Part1.SwitchOn() {} // ICompound1.IPart1
void DoPart1Specific() {} // ICompound1.IPart1
Guid Part2.Id => Guid.Empty; // ICompound1.IPart2
void Part2.SwitchOn() {} // ICompound1.IPart2
void DoPart2Specific() {} // ICompound1.IPart2
}
Only not-so-nice and partial solution I'm able to figure out is to replicate all the common stuff in each interface definition, which is too verbose and error prone (in this case the explicit implementation works and let's say it does not matter that the Compound class members can't be public), but there is no base interface available )o:
public interface IPart1Ex
{
Guid Id {get;}
void SwitchOn();
void DoPart1Specific();
}
public interface IPart2Ex
{
Guid Id {get;}
void SwitchOn();
void DoPart2Specific();
}
public interface ICompound1Ex : IPart1Ex, IPart2Ex {}
public class CompoundEx : ICompound1Ex
{
Guid IPart1Ex.Id => Guid.Empty;
void IPart1Ex.SwitchOn() {}
void IPart1Ex.DoPart1Specific() {}
Guid IPart2Ex.Id => Guid.Empty;
void IPart2Ex.SwitchOn() {}
void IPart2Ex.DoPart2Specific() {}
}
It seems like you don't want to inherit from interfaces at all, but rather use composition. Your Compound class needs to hold an instance for Part1 and an instance for Part2. This would give something like:
public interface IPart {
Guid Id { get; }
void SwitchOn();
void Execute();
}
public class Compound
{
private readonly IPart _part1;
private readonly IPart _part2;
public Compound(IPart part1, IPart part2)
{
_part1 = part1;
_part2 = part2;
}
public Guid Part1Id { get { return _part1.Id; } }
public void Part1SwitchOn() { _part1.SwitchOn(); }
public void DoPart1Specific() { _part1.Execute(); }
public Guid Part2Id { get { return _part2.Id; } }
public void Part2SwitchOn() { _part2.SwitchOn(); }
public void DoPart2Specific() { _part2.Execute(); }
}
Or a simpler class would just be:
public class Compound
{
public Compound(IPart part1, IPart part2)
{
Part1 = part1;
Part2 = part2;
}
public IPart Part1 { get; private set; }
public IPart Part2 { get; private set; }
}
and then access them in the calling code using:
var compound = MyMethodWhichCreatesCompound();
var id1 = compound.Part1.Id;
compound.Part2.Execute();
//etc
I think using the new keyword on interface member definitions can help you:
public interface IBase
{
Guid Id {get;}
void SwitchOn();
}
public interface IPart1 : IBase
{
new Guid Id {get;}
new void SwitchOn();
void DoPart1Specific();
}
public interface IPart2 : IBase
{
new Guid Id {get;}
new void SwitchOn();
void DoPart2Specific();
}