Background info
I have a set of interfaces/classes as follows. For the sake of simplicity imagine more properties, collections etc.
interface IMaster
{
//Some properties
}
interface IB : IMaster
{
string PropOnA { get; set }
}
interface IC : IMaster
{
string PropOnB { get; set }
}
class B : IB
class C : IC
...
These contracts were designed to store data(which is held in a slightly different format in each case). There is a lot of code that uses these contracts to get the data, format it, process it, write etc.
We have developed an entire library that does not see the concrete implementations(B,C) of any of these contracts by inverting control and allow the user to use our 'default implementations' for each contract or just loading in their own. We have registry where the user can register a different implementation.
To this end I have implemented a kind of strategy pattern where there exists a strategy for each contract type based on the task at hand. For the sake of simplicity lets say the task is writing, in reality it is much more complicated.
interface IWriteStrategy
{
public Write(IMaster thing);
}
class WriterA : IWriteStrategy
class WriterB : IWriteStrategy
etc
The above concrete strategies are also never 'seen' in our library, the client must register their own implementation or our default version.
Design flaw??
I am not liking the cast in every strategy that is now necessary.
public classWriterA : IWriteStrategy
{
public void Write(IMaster thing)
{
if(thing is IA thingA)
//do some work
}
}
public classWriterB : IWriteStrategy
{
public void Write(IMaster thing)
{
if(thing is IB thingB)
//do some work
}
}
What we want to do is be able to loop through a list of IMaster objects and run some operations.
foreach(var thing in Things)
{
var strategy = GetStrategy(thing.GetType()); //this gets the strategy object from our `registry` if one exists
strategy.Execute(thing);
}
The above design allows this but there seems to be a flaw which I cant for the life of me spot a solution to. We have to cast to the specific interface within each strategy implementation.
I have tried with generics, but just cant seem to nail it.
Question
What would be a better way of designing this to avoid the cast but still be able to loop through a list of IMaster things and treat them the same? Or is the cast absolutely necessary here?
I am trying to follow a SOLID design but feel the cast is messing with this as the client implementing the strategies will have to do the cast in order to get anything to work within the Write method.
[Edit]
I have updated the classes implementing the IWriteStrategy.
If you rarely add new IMaster specializations, but often add new operations OR need to make sure operation providers (e.g writer) needs to support ALL specializations then the Visitor Pattern is a perfect fit.
Otherwise you basically need some kind of service locator & registration protocol to map operation providers/strategies to IMaster specializations.
One way you could do it is define generic interfaces such as IMasterWriter<T> where T:IMaster which can then be implemented like IBWriter : IMasterWriter<IB> which defines the mapping.
From that point you only need a mechanism that uses reflection to find a specific IMasterWriter implementor for a given type of IMaster and decide what to do if it's missing. You could scan assemblies early to detect missing implementations at boot rather than failing later too.
Maybe it is appropriate to use Strategy pattern and just give an implementation and execute it. Let me show an example.
interface IMaster
{
void ExecuteMaster();
}
class MasterOne : IMaster
{
public void ExecuteMaster()
{
Console.WriteLine("Master One");
}
}
class MasterTwo : IMaster
{
public void ExecuteMaster()
{
Console.WriteLine("Master Two");
}
}
and
interface IWriteStrategy
{
void Write(IMaster thing);
}
class WriterA : IWriteStrategy
{
public void Write(IMaster thing)
{
Console.WriteLine("Writer A");
thing.ExecuteMaster();
}
}
class WriterB : IWriteStrategy
{
public void Write(IMaster thing)
{
Console.WriteLine("Writer B");
thing.ExecuteMaster();
}
}
and code to execute:
static void Main(string[] args)
{
List<IWriteStrategy> writeStrategies = new List<IWriteStrategy>()
{
new WriterA(),
new WriterB()
};
List<IMaster> executes = new List<IMaster>()
{
new MasterOne(),
new MasterTwo()
};
for (int i = 0; i < writeStrategies.Count(); i++)
{
writeStrategies[i].Write(executes[i]);
}
}
what about this, you will have all your casts in one strategy factory method:
public interface IWriterStrategy
{
void Execute();
}
public class WriterA : IWriterStrategy
{
private readonly IA _thing;
public WriterA(IA thing)
{
_thing = thing;
}
public void Execute()
{
Console.WriteLine(_thing.PropOnA);
}
}
public class WriterB : IWriterStrategy
{
private readonly IB _thing;
public WriterB(IB thing)
{
_thing = thing;
}
public void Execute()
{
Console.WriteLine(_thing.PropOnB);
}
}
public static class WriterFactory
{
public static List<(Type Master, Type Writer)> RegisteredWriters = new List<(Type Master, Type Writer)>
{
(typeof(IA), typeof(WriterA)),
(typeof(IB), typeof(WriterB))
};
public static IWriterStrategy GetStrategy(IMaster thing)
{
(Type Master, Type Writer) writerTypeItem = RegisteredWriters.Find(x => x.Master.IsAssignableFrom(thing.GetType()));
if (writerTypeItem.Master != null)
{
return (IWriterStrategy)Activator.CreateInstance(writerTypeItem.Writer, thing);
}
throw new Exception("Strategy not found!");
}
}
public interface IMaster
{
//Some properties
}
public interface IA : IMaster
{
string PropOnA { get; set; }
}
public interface IB : IMaster
{
string PropOnB { get; set; }
}
public interface IC : IMaster
{
string PropOnC { get; set; }
}
public class ThingB : IB
{
public string PropOnB { get => "IB"; set => throw new NotImplementedException(); }
}
public class ThingA : IA
{
public string PropOnA { get => "IA"; set => throw new NotImplementedException(); }
}
public class ThingC : IC
{
public string PropOnC { get => "IC"; set => throw new NotImplementedException(); }
}
internal static class Program
{
private static void Main(string[] args)
{
var things = new List<IMaster> {
new ThingA(),
new ThingB()//,
//new ThingC()
};
foreach (var thing in things)
{
var strategy = WriterFactory.GetStrategy(thing); //this gets the strategy object from our `registry` if one exists
strategy.Execute();
}
}
}
Related
I have this class Project which I want to extract an interface out of, since we're going to work with different types of projects. One of the properties of Project however is called Data:
class Project {
public Data D {get;}
public void SomeSpecificMethodReferencingData()
{
D.SomeSpecificMethod();
}
}
class Data {
public void SomeGenericMethod() { }
public void SomeSpecificMethod() { }
}
Now, Data needs to be extracted as an interface as well (but only defining the SomeGenericMethod(). I am currently using this:
interface IProject {
IData D {get;}
}
interface IData {
void SomeGenericMethod();
}
class Data : IData {
public void SomeGenericMethod() { }
public void SomeSpecificMethod() { }
}
class OtherData : IData {
public void SomeGenericMethod() { }
public int SomeOtherSpecificMethod(float someArgument) { }
}
class Project : IProject {
public IData D { get; }
public void SomeSpecificMethodReferencingData()
{
D.SomeSpecificMethod(); // this does not work!
(D as Data).SomeSpecificMethod(); // this looks stupid!
}
}
class OtherProject : IProject {
public IData D { get; }
public void SomeOSpecificMethodReferencingOtherData()
{
var i = D.SomeOtherSpecificMethod(14.0f); // this does not work!
var i = (D as OtherData).SomeOtherSpecificMethod(14.0f); // this looks stupid!
}
}
The problem I run into is that within the Project class, I reference the SomeSpecificMethod. When I extract an interface for Data however, I first have to cast it from IData to be able to reference the specific method. This is not preferrable as the IData ALWAYS is an instance of Data for this Project. When I build my OtherProject I will create an OtherData for it, so to get pairs of xxxProject and xxxData implementations.
Is there a design pattern of some sort to help me building pairs of related and referenced classes? Like the Abstract Factory, but better?
You may use generics for that:
interface IProject<T> where T: IData {
T D {get;}
}
Now your different projects are this:
class Project : IProject<Data>
{
public Data D { get; }
public void SomeSpecificMethodReferencingData()
{
D.SomeSpecificMethod(); // D is of type Data
}
}
class OtherProject : IProject<OtherData> {
public OtherData D { get; }
public void SomeOSpecificMethodReferencingOtherData()
{
D.SomeOtherSpecificMethod(14.0f); // D is of type OtherData
}
}
you can have 3 separate interfaces:
interface IData:ISpecificData, IGenericData
{
}
interface ISpecificData
{
void SomeSpecificMethod();
}
interface IGenericData
{
void SomeGenericMethod();
}
you can use only one of the interfaces when you need only one of the methods, and use IData when you need both
In class Project you are referencing SomeSpecificMethod of Data class.
You are NOT using anything from IData interface - so using IData in Project class has no sense.
It is possible to do it as in your examples, and it will work - but it is "wrong way".
(D as Data).SomeSpecificMethod(); // this looks stupid!
It looks stupid - but from other reasons. What if D is not Data, but OtherData ? It will be perfectly correct at compile time, but it will blow up during runtime!
i'm trying to build a sort of framework for some base process in an app. There is some common behavior where i have to execute some operations but these operations are different depending on some scenarios. I have done something i'm not sure if it's considered a bad practice to make something like this:
public interface IMyDto
{
string makerIdentifier { get; set; }
}
public class DtoOne:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteOne
}
public class DtoTwo:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteTwo
}
public abstract class AbstractMaker
{
public abstract void DoSomething(IMyDto myInterface);
}
public class ConcreteMakerOne:AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoOne;
// If concrete is not null..do stuff with DtoOne properties
}
}
public class ConcreteMakerTwo : AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoTwo;
// If concrete is not null..do stuff with DtoTwo properties
}
}
public class Customer
{
public void MakeSomething(IMyDto myDto)
{
var maker = GetMaker();
maker.DoSomething(myDto);
}
private AbstractMaker GetMaker()
{
//Stuff to determine if return ConcreteOne or ConcreteTwo
}
}
The code im not happy with is the:
var concrete = myInterface as DtoOne;
I would appreciate a lot if someone could give me some advide or tips about a pattern or good oop practice for this scenario.
It's not clear what all of your use cases are, but one option might be generics:
public abstract class AbstractMaker<T> where T:IMyDto
{
public abstract void DoSomething(T myInterface);
}
public class ConcreteMakerTwo : AbstractMaker<DtoTwo>
{
public override void DoSomething(DtoTwo myInterface)
{
// now you are certain that myInterface is a DtoTwo
}
}
I am not sure if I understand correctly what are you asking about, but why not just put method DoSomething in IMyDto and implement it differently in DtoOne, DtoTwo, etc.? There would be only one Maker and would always call the same method.
I would like to restrict access to methods, depending on the type passed in. In my particular situation, I am developing a UDP "manager" if you will.
I want my UDPManager to be used for different things. For example, I might have 1 UDPManager for the communications between client and server, and another UDPManager to handle the communications between server and another server.
I have defined an enum which specifies the type of UDPManager. So for example, ManagerType.A = 1 and...
ManagerType.B = 2
The UDPManager has certain events that can be subscribed to and I do not want them available if these events are not relevant, given the type of UDPManager.
Here is an example of a class
public class Something
{
public int SomethingsType { get; set; }
public void A() { }
public void B() { }
}
How can I make it so that if SomethingsType == MessageType.A, then MessageType.B is not available (ie it is private)?
For further clarity, if I type:
Something something = new Something();
someting.SomethingsType = 1
I do not want something.B() to be available.
UPDATE
I apologise for mentioning runtime. What I mean is, I do not want said method (B) available if said SomethingsType is A.
Interfaces to the rescue:
public interface IUdpManagerA
{
void A();
}
public interface IUdpManagerB
{
void B();
}
public class UdpManager : IUdpManagerA, IUdpManagerB
{
public void A() { }
public void B() { }
}
public class UdpManagerFactory
{
private UdpManager Create() => new UdpManager();
public IUdpManagerA CreateOfA() => Create();
public IUdpManagerB CreateOfB() => Create();
}
UdpManagerFactory factory = new UdpManagerFactory();
IUdpManagerA a = factory.CreateOfA();
IUdpManagerB b = factory.CreateOfB();
Interfaces are a powerful tool to publish certain members while others can remain hidden.
While you might say yeah, but you can always cast IUdpManagerA to IUdpManagerB and vice versa to gain access to hidden members, and my answer is **this isn't safe because there's no clue that IUdpManagerA also implements IUdpManagerB and vice versa.
Oh, and I forgot to mention that you should throw away the ManagerType enumeration, because with interfaces you can always check if a given instance is A or B:
object instance = factory.CreateA();
if(instance is IUdpManagerA)
{
}
if(instance is IUdpManagerB)
{
}
or using as operator:
object instance = factory.CreateA();
IUdpManagerA a = instance as IUdpManagerA;
IUdpManagerB b = instance as IUdpManagerB;
if(a != null)
{
}
else if(b != null)
{
}
This is an extreme simple version of a factory build method based of an enum:
public enum ManagerType
{
A,B
}
public abstract class UDPManager
{
}
public class SomethingA : UDPManager
{
public void A()
{}
}
public class SomethingB : UDPManager
{
public void B()
{}
}
public class UdpManagerFactory
{
public UDPManager Build(ManagerType type)
{
if (type == ManagerType.A)
return new SomethingA();
if(type == ManagerType.B)
return new SomethingB();
throw new Exception("type not found");
}
}
I'm using Unity in with C#. I have an interface I call IConnectionStringLoader, which have two derived interfaces.
public interface IConnectionStringLoader
{
string Get();
void Write();
}
public interface IDbConnectionStringLoader : IConnectionStringLoader
{
}
public interface IMetaDataConnectionStringLoader : IConnectionStringLoader
{
}
It has only one implementation:
public class ConnectionStringLoader : IDbConnectionStringLoader, IMetaDataConnectionStringLoader
{
private readonly string _connectionStringName;
public ConnectionStringLoader(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
public string Get()
{
var cs = ConfigurationManager.ConnectionStrings[_connectionStringName];
if (cs != null)
{
return cs.ConnectionString;
}
return null;
}
public void Write()
{
Console.WriteLine(_connectionStringName);
}
}
My registration looks like this:
container.RegisterType<IMetaDataConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("MetaConnection"));
container.RegisterType<IDbConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("DbConnection"));
The point of the interfaces is that I can inject the different interfaces in my classes and get the correct connectionstring for each implementation. But the problem is that whatever registration is done last will overwrite the previous one.
var foo = _container.Resolve<IDbConnectionStringLoader>();
var bar = _container.Resolve<IMetaDataConnectionStringLoader>();
foo.Write();
bar.Write();
Output is:
DbConnection
DbConnection
If I invert the order of the registration the output will be MetaConnection twice. So my conclusion so far is that the last registration overwrites the previous one. However, if I change the implementation to a derived class it works:
public class SomeOtherConnectionStringLoader : ConnectionStringLoader
{
public ConnectionStringLoaderImpl(string connectionStringName) : base(connectionStringName)
{
}
}
And change the registrations:
container.RegisterType<IMetaDataConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("MetaConnection"));
container.RegisterType<IDbConnectionStringLoader, SomeOtherConnectionStringLoader >(new InjectionConstructor("DbConnection"));
Now everything works, but I don't understand why. I've tried different lifetimemanagers, but with the same result. I thought Unity would try to create an instance of ConnectionStringLoader with the "correct" injectionparameter based on the interface, but there's seems to be some other logic at play here.
Any suggestions why the registrations overwrite each other?
Honestly speaking, the way you are using the interfaces looks strange to me because there are two interfaces implemented only by the same class. I would find more natural to follow the next approach using registration names:
// If it is a loader the Write method makes no sense (IConnectionStringRepository?)
public interface IConnectionStringLoader
{
string Get();
void Write();
}
public class ConnectionStringLoader : IConnectionStringLoader
{
private readonly string _connectionStringName;
public ConnectionStringLoader(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
public string Get()
{
var cs = ConfigurationManager.ConnectionStrings[_connectionStringName];
if (cs != null)
{
return cs.ConnectionString;
}
return null;
}
public void Write()
{
Console.WriteLine(_connectionStringName);
}
}
Registrations:
container.RegisterType<IConnectionStringLoader, ConnectionStringLoader>("Database", new InjectionConstructor("MetaConnection"));
container.RegisterType<IConnectionStringLoader, ConnectionStringLoader>("Metadata", new InjectionConstructor("DbConnection"));
Resolutions:
var foo = _container.Resolve<IConnectionStringLoader>("Database");
var bar = _container.Resolve<IConnectionStringLoader>("Metadata");
foo.Write();
bar.Write();
I'm not familiar with Unity. But it seems they are mapping to same instance. So you should change lifetime of ConnectionStringLoader (Per dependency).
If you will not share instance, why do you put all things in one class ? ConnectionStringLoader Methods = IDbConnectionStringLoader methods + IMetaDataConnectionStringLoader methods.
When you resolve IDbConnectionStringLoader it will not use IMetaDataConnectionStringLoader methods which is already in instance (vice versa it's true).
Crating two different derived class is better at this point:
Abstract class:
public abstract class ConnectionStringLoader : IConnectionStringLoader
{
private readonly string _connectionStringName;
public ConnectionStringLoader(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
public string Get()
{
var cs = ConfigurationManager.ConnectionStrings[_connectionStringName];
if (cs != null)
{
return cs.ConnectionString;
}
return null;
}
public void Write()
{
Console.WriteLine(_connectionStringName);
}
}
Derived Classes:
public sealed class DbConnectionStringLoader : ConnectionStringLoader, IDbConnectionStringLoader
{
public DbConnectionStringLoader(string connectionStringName):base(connectionStringName)
{
}
//Implement methods here just belongs to IDbConnectionStringLoader
}
public sealed class MetaDataConnectionStringLoader : ConnectionStringLoader, IMetaDataConnectionStringLoader
{
public MetaDataConnectionStringLoader(string connectionStringName):base(connectionStringName)
{
}
//Implement methods here just belongs to IMetaDataConnectionStringLoader
}
Surprisingly it does call ConnectionStringLoader ctor twice, but with same injection member. If you look at container.Registrations, there are indeed two registrations so it is not override one with other. I did look at implementation of RegisterType, but didn't get my head around it.
One alternative is to name your registrations, not sure if it fits into your overall unity bootstrap strategy.
container.RegisterType<IMetaDataConnectionStringLoader, ConnectionStringLoader>("bar", new InjectionConstructor("MetaConnection"));
container.RegisterType<IDbConnectionStringLoader, ConnectionStringLoader>("foo", new InjectionConstructor("DbConnection"));
var foo = container.Resolve<IDbConnectionStringLoader>("foo");
var bar = container.Resolve<IMetaDataConnectionStringLoader>("bar");
I'm trying to design a few classes for a game, but I'm not sure I'm doing it right.
I have two classes: Actor and Building.
These have a few subclasses: Policeman, Fireman and PoliceStation, FireStation.
I want to be able to put all these items together in a list to iterate through later, so I've added a base class: GameEntity.
So what I have is this:
public abstract class GameEntity:
{
public GameEntity()
{
}
}
public class Actor: GameEntity
{
public int _speed;
public TileSprite _UI;
public Actor()
{
}
public bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
public virtual void OnClick()
{
//Do stuff here
}
public void DoActing()
{
}
}
public class Policeman: Actor
{
public Policeman()
{
_speed = 10;
}
public override void OnClick()
{
//Do stuff
}
}
public class Building: GameEntity
{
public TileSprite _UI;
public Building()
{
}
public bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
public virtual void OnClick()
{
//Do stuff here
}
public void DoBuilding()
{
}
}
public class PoliceStation: Building
{
public PoliceStation()
{
}
public override void OnClick()
{
//Do stuff
}
}
Now, I want to be able to do this:
List<GameEntity> Entities = new List<GameEntity>();
Actor a1 = new PoliceMan();
Building b1 = new PoliceStation
Entities.Add(a1);
Entities.Add(b1);
foreach(GameEntity ent in Entities)
{
if (ent.CollidesWith(something))
{
ent.OnClick();
//If Actor then do
ent.DoActing();
//If Building then do
ent.DoBuilding();
}
}
Now, in order to do the last bit, would it be best if I implement an interface that contains the OnClick and CollidesWith, or can I do it with inheritance?
If so, how would I do this?
Cheers.
This is only to give you the idea, I guess that's what you need.
public interface IGameEntity
{
bool CollidesWith();
void OnClick();
void DoActing();
}
public class Actor : IGameEntity { //Interface implemented }
public class Building: IGameEntity { //Interface implemented }
public class Policeman: IGameEntity { //Interface implemented }
public class Fireman: IGameEntity { //Interface implemented }
public class FireStation: IGameEntity { //Interface implemented }
In your client object just do something like this:
List<IGameEntity> entities = new List<IGameEntity>()
{
new Actor(),
new Building(),
new Policeman(),
new Fireman(),
new Fireman()
};
foreach (IGameEntity entity in entities)
{
entity.CollidesWith();
entity.OnClick();
entity.DoActing();
}
Number of ways to go here.
If all GameEntities can be clicked on then you could add an OnClick event property to the base class.
If Not then I'd have an Interface IClick and then implement that on clickable entities.
Collision, depends.
Building don't move about so they can't collide with anything, but they can be collided with and so for instance you might want do a damage rountine, which then suggests a destroyed, routine a repair routine maybe.
There's no right answer, but
Three code smells would be a
A Base class with nothing in it.
A very deep inheritance hierarchy (more than two levels is cause for suspicion in my book)
So if you start seeing GameEntity -> BuildingEntity -> ActiveBuildingEntity -> RepairableBuildingEntity, you are in a mess that's about to get messier.
And above all a base class with do nothing methods in it that only exist because you need to add behaviour (override) in some descendants.
Don't be scared about having a few interfaces. IClick, ICollision, IDamage, IRepair etc. It's way better than implying a building can crash into a car.
You could do something like this:
public interface IGameEntity
{
void OnClick();
bool CollidesWith(Vector2 pos);
void Do();
}
public abstract class Actor: IGameEntity
{
public int _speed;
public TileSprite _UI;
public virtual bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
// can be marked virtual with implementation if you want a default
// this way base classes will be forced to implement their own implementation
public abstract void OnClick();
// can be marked virtual with implementation if you want a default
// this way base classes will be forced to implement their own implementation
public abstract void Do();
}
public class Policeman: Actor
{
public Policeman()
{
_speed = 10;
}
public override void OnClick()
{
//Do stuff
}
public override void Do()
{
//Do Acting for Police
}
}
public abstract class Building: IGameEntity
{
public TileSprite _UI;
public bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
public abstract void OnClick();
public abstract void Do();
}
public class PoliceStation: Building
{
public PoliceStation()
{
}
public override void OnClick()
{
//Do stuff
}
public override void Do()
{
// Do Building
}
}
If Game Entity is just an interface then there is no need to make it an abstract class. If Actor and Building can never exist as a stand alone object then they should be abstract. If DoActing, DoBuilding, and OnClick must be overridden by the base classes then you can mark them abstract in actor and Building.
I followed norlesh's suggestion to just have one method Do. You could also make Actor and Building have their own abstract methods and IGameEntity would not have Do. Then you would put an if statement and check the if each object is of type builder then they would run the build and if of type actor then run act.
I think the way of having one method is better, since you eliminate one step. From a design perspective I'm not sure but it feels the same to me either way.
List<IGameEntity> Entities = new List<IGameEntity>();
Actor a1 = new PoliceMan();
Building b1 = new PoliceStation();
Entities.Add(a1);
Entities.Add(b1);
foreach(IGameEntity ent in Entities)
{
if (ent.CollidesWith(something))
{
ent.OnClick();
ent.Do();
}
}
Adding a virtual doStuff() to GameEntity and overriding it in the child classes instead of having unique method names like DoActing and DoBuilding then calling that from your loop should do what you want.