Factory design pattern and dependency injection implementation - c#

Currently I am trying to implement some design structures and the factory seems most appropriate and as far as dependency injection goes I much prefer constructor injection. However the issue arises that not all my products require the same dependancies, which kind of messes with the pattern...
My abstract Factory .get() method will have to look like so
abstract class AbstractSpellFactory
{
public abstract WCSpell get(SpellSubType sSubType,SpellCard,int a,int b,int c,int d);
}
and for completion sake here is the spell class in the context of what i am doing/using
public abstract class WCSpell
{
public abstract void CastSpell();
}
and then i can use it like
AbstractSpellFactory aSpellFactory = SpellFactory.createSpellFactory(SpellType.buff);
WCSpell spell = aSpellFactory.get(SpellSubType.Positive,sCard,1,2,3,4);//OK
spell.CastSpell();
aSpellFactory = SpellFactory.createSpellFactory(SpellType.rotate);
spell = aSpellFactory.get(SpellSubType.clockwise,sCard,0,0,0,0);//Non-used/Needed values...
spell.CastSpell();
So this works, but first and foremost the fact that the rotate spell does not need the integers is a little inelegant, but the biggest problem of all is if i add any new spells that have different dependancies the AbstractSpellFactory.get(...) method argument parameters are just going to get bigger and based on the spell type it might not even need/have the values being passed in.
So I am a tad stuck, does anyone have any suggestions?
Psuedo Implementation of code above
Spell Factory class
static class SpellFactory
{
public static AbstractSpellFactory createSpellFactory( SpellType sType )
{
AbstractSpellFactory sFactory = null;
switch(sType)
{
case SpellType.kBuff:
{
sFactory = new SpellBuffFactory();
}
break;
case SpellType.kRotateClockWise:
{
sFactory = new SpellRotateFactory();
}
break;
}
return sFactory;
}
}
Buff Spell Factory
public class SpellBuffFactory : AbstractFactory
{
public override Spell get( SpellSubType sSubType,SpellCard sCard,int a,int b,int c,int d)
{
Spell spell = null;
switch(sSubType)
{
case Positive:
{
spell = new BuffSpell(a,b,c,d,sCard);
}
break;
case Negative:
{
spell = new BuffSpell(-a,-b,-c,-d,sCard);//some check to make sure all values are negative
}
}
return spell;
}
}
Rotate Spell Factory
public class SpellRotateFactory : AbstractFactory
{
public override Spell get( SpellSubType sSubType,SpellCard sCard,int a,int b,int c, int d)
{
Spell spell = null;
switch(sSubType)
{
case Clockwise:
{
spell = new WCRotateSpell(WCRotateSpell.RotationDirection.Clockwise,sCard);
}
break;
case CounterClockwise:
{
spell = new WCRotateSpell(WCRotateSpell.RotationDirection.CounterClockwise,sCard);
}
}
return spell;
}
}

Whenever I see that many parameters I figure something could be improved. Adding your valid concern for dependency injection and new features only makes it more important to consider your options which, as I see it, are as follows:
Every factory needs work orders. Strongly-type one base and inherit that, extend with interfaces as you already seem familiar.
public interface ICastable()
{
bool ValidateTarget();
// ICastable will require implementors to define Cast;
// forcing a descendant (or the ancestor, I suppose) to
// provide the details of how to cast that spell. The parameter
// is also a type that you control for spell-casting information
void Cast(InvocationInfo info);
}
// really common info needed to cast a spell
public class InvocationInfo
{
TargetableEntity Target;
ControllableEntity SpellCaster;
List<SpellRegents> ReagentsChosen;
MoonPhases MoonPhase;
bool IsMercuryInRetrograde;
}
// base spell class
public class Spell
{
public string Name { get; set; }
public int EnergyCost { get; set; }
}
// actual castable spell
public class MagicMissile : Spell, ICastable
{
public void Cast(InvocationInfo details)
{
details.SpellCaster.SpendMana(this.EnergyCost);
if (details.Target.Location.DistanceFrom(details.SpellCaster) > this.Range)
{
details.SpellCaster.SendMessage(Messages.OutOfRange);
return;
}
// ...
}
}
Don't forget you can make use of the generic type :
public Spell Hang<T>(InvocationInfo details) where T: Spell
{
if(details.SpellCaster.Energy < T.EnergyCost)
throw new InsufficientEnergyException();
// ...
}
var spell = SpellFactory.Hang<Rotation>();
If that sounds like too much work consider the cheap way out is the dynamic type to which you can assign whatever you like and interrogate for whatever your constructor overloads need.
In either case I suspect the polymorphic answers are always going to be better. I would always recommend solutions adhere to the strengths of the language and framework: strongly typed, object oriented, readable, simple.
I'll suggest that you're on, or at least considering, the right path; you lower your duplication and dependencies by overloading constructors (or some kind of "make" method) while increasing readability if you strongly type or weakly type some kind of parameter structure to the factory.

Related

Better way to solve my class hierarchy problem than Unsafe.As cast to a child class?

(I'm writing about matrices, but don't worry, this is not a maths question and presumes no maths knowledge.)
I have a Matrix class that has three fields
double[] Data;
int Rows;
int Columns;
and defines hundreds of mathematical operations.
Additionally, I have a SymmetricMatrix : Matrix subclass that has no instance fields of its own, that offers all of the operations above via inheritance, offers some additional operations (like EigenvalueDecomposition), and finally repeats some definitions with a new keyword to change the return type to SymmetricMatrix.
For example, if Matrix has
public Matrix MatrixMultiplication(Matrix otherMatrix)
public Matrix ScaledBy(double scalar)
then SymmetricMatrix would simply inherit the MatrixMultiplication but it would change the ScaledBy to return a SymmetricMatrix.
Rather than reimplementing ScaledBy , I define it via
// SymmetricMatrix.cs
public new SymmetricMatrix ScaledBy(double scalar) => base.ScaledBy(scalar).AsSymmetricMatrix()
// Matrix.cs
public SymmetricMatrix AsSymmetricMatrix() => Unsafe.As<SymmetricMatrix>()
(I'm using new instead of virtual+override for reasons that don't matter for the purposes of this question).
I found this approach to work surprisingly well, and it allows me to be super succinct in defining SymmetricMatrix.cs. The obvious downside is that it may exploit unsupported behavior (?) and that it confuses the debugger I'm using a lot (the runtime type of the result of the cast is Matrix which is not a subclass of its compile time type SymmetricMatrix, and yet, all the operations defined on SymmetricMatrix succeed because the data held by both classes is the same)
Questions
Do you foresee any problems with my approach that I haven't though of?
Might my approach break with the next dotnet version?
Do you think there are cleaner ways of achieving what I want? I had a few ideas but none seem to work out cleanly. For example, I cannot encode which operations preserve Child classes in the parent class via
class Matrix<T> where T : Matrix
...
T ScaledBy(double other)
because whether or not an operation preserves a Child class is knowledge only the Child can have. For example, SymmetricPositiveDefiniteMatrix would NOT be preserved by ScaledBy.
Alternatively, I could use encapsulation over inheritance and define
class BaseMatrix
{
...lots of operations
}
...
class Matrix : BaseMatrix
{
private BaseMatrix _baseMatrix;
...lots of "OperationX => new Matrix(_baseMatrix.OperationX)"
}
class SymmetricMatrix : BaseMatrix
{
private BaseMatrix _baseMatrix;
...lots of "OperationX => preserving ? new SymmetricMatrix(_baseMatrix.OperationX) : new Matrix(_baseMatrix.OperationX);"
}
That's very sad to code up though, because I'd have to manually propagate every change I make to BaseMatrix to, at the moment, four extra classes, and users would have to manually cast SymmetricMatrixs to Matrix in lots of scenarios.
Finally, I could simply not offer subclasses and rather have flags like bool _isSymmetric and encode the operations that preserve symmetry/positivity/... by changing/setting the flags in all my methods. This is sad too, because :
Users would then be able to write Matrix.EigenvalueDecomposition() just to have this break at runtime with a You have to promise me that your matrix is symmetric because I only implemented EigenvalueDecomposition for that case error
It would be too easy to forget resetting a flag when it's not preserved and then accidentally running an operation that assumes symmetry (which BLAS does by simply ignoring half of the matrix)
I like being able to specify in the type system rather than the comments that, e.g., the matrix I return from CholeskyFactor is lower triangular (conventions differ and some may expect an upper triangular matrix)
Users wouldn't see which flags are currently set so they wouldn't know whether I use the "specialized" version of a given algorithm and likely end up using .SetSymmetric() unnecessarily all over the place just to be safe.
Unless I missed a requirement, you could implement what you want using generics
A (not so brief) example :
public abstract class BaseMatrix<TMatrix> where TMatrix : BaseMatrix<TMatrix>
{
// Replace with how you actuallt are storing you matrix values
protected object _valueStore;
// common initialization (if required), if not keep empty
protected BaseMatrix()
{
}
// necessary to copy the value store.
protected BaseMatrix(object valueStore)
{
this._valueStore = valueStore;
}
public virtual TMatrix ScaledBy(double scalar)
{
// implementation
return default;
}
}
public class Matrix : BaseMatrix<Matrix>
{
}
public class SymmetricMatrix : BaseMatrix<SymmetricMatrix>
{
public SymmetricMatrix() : base(){}
// allows to build from another matrix, could be internal
public SymmetricMatrix(object valueStore) : base(valueStore){}
public override SymmetricMatrix ScaledBy(double scalar)
{
return base.ScaledBy(scalar);
}
}
public class SymmetricPositiveDefiniteMatrix : BaseMatrix<SymmetricPositiveDefiniteMatrix>
{
// If we *know* the type is not the same after this method call, we mask with a new one retirning the target type
// A custom cast operator will handle the conversion
public new SymmetricMatrix ScaledBy(double scalar)
{
return base.ScaledBy(scalar);
}
// Added to allow a cast between SymmetricPositiveDefiniteMatrix and SymmetricMatrix
// in this example, we keep the value store to not have to copy all the values
// Depending on project rules could be explicit instead
public static implicit operator SymmetricMatrix(SymmetricPositiveDefiniteMatrix positiveSymmetricMatrix)
{
return new SymmetricMatrix(positiveSymmetricMatrix._valueStore);
}
}
Which would make the ScaledBy(double) method available in each type of matrix, and returning the type of the matrix it was called on.
And it would comply with your requirement not to have to redefine most methods / properties in each class.
Obviously, you can override methods in childrens to either do more before or after the base() call or even define an entirely different implementation.
One shortcoming would be if you needed one type to inherit from a class inheriting from BaseMatrix<TMatrix>. You'd have no way of changing the generic type parameter.
Alternatively if this really doesn't match your needs and prefer to go the encapsulation route, you could have a look at source generators since the code seems to be quite repetitive.
As we were talking with colleagues about procedural programming, here's my 2 cents about your problem.
The underlying data structure is of (and keep its) specific form:
struct DataMatrix
{
public double[] Data;
public int Rows;
public int Columns;
}
As you have specific behaviour depending on the type, you can flag it in a specialized type instead of strong-typing it:
struct Matrix
{
public DataMatrix DataMatrix;
public bool isSymmetrical;
public bool isDefinite;
public bool isUpperTriangular;
}
Then, you may call your methods from one place using said flagged type:
// MatrixManager acts solely as a namespace for convenient method grouping
public static class MatrixManager
{
//Consider a void return for each method, as matrix.DataMatrix is(/may be) the only affected field
public static Matrix Multiplication(Matrix matrix, Matrix otherMatrix) => /*..multiply matrix.DataMatrix with otherMatrix.DataMatrix then return matrix.*/;
public static Matrix ScaledBy(Matrix matrix, double scalar) => /*..scale matrix.DataMatrix with scalar then return matrix.*/;
public static void SetSymmetrical(Matrix matrix) { if (!matrix.isSymmetrical) matrix.isSymmetrical = true; }
public static Matrix UnavailableOperationIfSymmetricalExample(Matrix matrix) => matrix.isSymmetrical ? matrix : EigenvalueDecomposition(matrix);
/*..hundreds of Matrix-based methods here..*/
public static Matrix EigenvalueDecomposition(Matrix matrix) { if (matrix.isSymmetrical) return matrix; /*..otherwise do decompose matrix.DataMatrix then return matrix.*/}
}
This way, you can specify the actual behaviour when calling a method with any flagged Matrix type (throw exception? call another method? return?), without having to bother with a behaviour-type tangled structure.
Hope that would suit your needs.
I think that the use of Unsafe.As() is indeed unsafe.
A major problem is this:
Matrix mat = new Matrix(/* whatever */);
SymmetricMatrix smat = mat.AsSymmetricMatrix();
Console.WriteLine(smat.GetType().FullName); // "Matrix"
So you have something declared as SymmetrixMatrix but its underlying type is in fact Matrix. I'm sure you can imagine the sort of horrible problems that could cause...
This approach also requires that the base class knows about its derived classes - a big no-no.
One way to solve issues like this it to make sure you can clone your objects in a way that works with inheritance. Then you can clone the original objects and return them, with a cast if necessary.
For example:
public class Matrix
{
public Matrix()
{
// Whatever
}
// Copy constructor; used for cloning.
public Matrix(Matrix other)
{
_data = other._data.ToArray();
}
public virtual Matrix ScaledBy(double scalar)
{
var result = Clone();
result.ScaleBy(scalar);
return result;
}
protected void ScaleBy(double scalar)
{
for (int i = 0; i < _data.Length; ++i)
{
_data[i] *= scalar;
}
}
protected virtual Matrix Clone()
{
return new Matrix(this);
}
readonly double[] _data = new double[16]; // For illustration.
}
public class SymmetricMatrix: Matrix
{
public SymmetricMatrix()
{
// Whatever
}
// Copy constructor; used for cloning.
public SymmetricMatrix(SymmetricMatrix other): base(other)
{
// No new fields to copy.
// Any newly added fields should be copied here.
}
public override SymmetricMatrix ScaledBy(double scalar)
{
// This cast will work because the underlying type returned from
// base.ScaledBy() really is SymmetricMatrix
return (SymmetricMatrix)base.ScaledBy(scalar);
}
protected override SymmetricMatrix Clone()
{
return new SymmetricMatrix(this);
}
}
public class SymmetricPositiveDefiniteMatrix: Matrix
{
// Doesn't override ScaledBy() so SymmetricPositiveDefiniteMatrix.ScaledBy() will return a Matrix.
protected override SymmetricPositiveDefiniteMatrix Clone()
{
// If SymmetricMatrix ever adds new fields to be cloned, they should be cloned here.
return Unsafe.As<SymmetricPositiveDefiniteMatrix>(base.Clone());
}
}
Now code like this returns the expected types:
var smatrix = new SymmetricMatrix();
var sresult = smatrix.ScaledBy(1.0);
Console.WriteLine(sresult.GetType().FullName); // "SymmetricMatrix"
var spmatrix = new SymmetricPositiveDefiniteMatrix();
var spresult = spmatrix.ScaledBy(1.0);
Console.WriteLine(spresult.GetType().FullName); // "Matrix"
As an example of code where Unsafe.As() can cause strange results, consider this code:
using System;
using System.Runtime.CompilerServices;
namespace ConsoleApp1;
static class Program
{
public static void Main()
{
var myBase = new MyBaseClass();
var pretendDerived = myBase.AsMyDerivedClass();
// Given the definition of MyDerivedClass, what do you think this will print?
Console.WriteLine(pretendDerived.Name());
}
}
public class MyBaseClass
{
public MyDerivedClass AsMyDerivedClass() => Unsafe.As<MyDerivedClass>(this);
}
public class MyDerivedClass
{
readonly string _name = "TEST";
public string Name() => _name;
}
As the documentation for Unsafe.As() states:
The behavior of Unsafe.As(o) is only well-defined if the typical
"safe" casting operation (T)o would have succeeded. Use of this API to
circumvent casts that would otherwise have failed is unsupported and
could result in runtime instability.
Thanks to all the creative answers, all of which I drew inspiration from.
I ended up combining encapsulation and inheritance, using a data-only TwoDimensionalArray and inheritance from a method-only (plus a single TwoDimensionalArray field) Matrix class:
class TwoDimensionalArray
{
double[] data;
int Rows;
int Columns
double Scale;
}
class Matrix
{
internal readonly TwoDimensionalArray _array;
public int Rows => _array.Rows;
public int Columns => _array.Columns;
public static Ones(int Rows, int Columns)
{
var data = new double[Rows * Column];
data.AsSpan().Fill(1);
return new Matrix(data, Rows, Columns, 1);
}
internal Matrix(TwoDimensionalArray array)
{
_array = array;
}
public Matrix ScaledBy(double scalar)
{
var output = Clone();
output.ScaleBy(scalar);
return output;
}
public void ScaleBy(double scalar)
{
_array.Scale *= scalar;
}
public Matrix Clone()
{
var newData = new double[array.data.Length];
array.data.AsSpan().CopyTo(newData);
return new Matrix(new TwoDimensionalArray(newData, Rows, Columns);
}
}
public class SymmetricMatrix : Matrix
{
internal SymmetricMatrix(TwoDimensionalArray array) => base(array);
public new SymmetricMatrix ScaledBy(double scalar) => base.ScaledBy(scalar).AsSymmetricMatrix();
public (Matrix, double[]) EigenvalueDecomposition()
{
//implementation
}
public new SymmetricMatrix Clone() => base.Clone().AsSymmetricMatrix();
}
class SymmetricPositiveDefiniteMatrix : SymmetricMatrix
{
internal SymmetricPositiveDefiniteMatrix(TwoDimensionalArray array) => base(array);
public Matrix CholeskyFactor()
{
//implementation
}
public new SymmetricPositiveDefiniteMatrix Clone() => base.Clone().AsSymmetricMatrix();
}
public static class MatrixExt
{
public SymmetricMatrix AsSymmetricMatrix(this Matrix matrix)
{
return new SymmetricMatrix(matrix._array);
}
public SymmetricPositiveDefiniteMatrix AsSymmetricMatrix(this Matrix matrix)
{
return new SymmetricPositiveDefiniteMatrix(matrix._array);
}
}
Note that the result of .AsSymmetricMatrix() is a view, not a clone (similar to, e.g., myArray.AsSpan() being a view of an array, not a copy). I needed TwoDimensionalArray to be a class, not a struct, so that all changes to the view, including rescaling and reshaping, are reflected in the original.

Refactoring class to get rid of switch case

Say I have a class like this for calculating the cost of travelling different distances with different modes of transportation:
public class TransportationCostCalculator
{
public double DistanceToDestination { get; set; }
public decimal CostOfTravel(string transportMethod)
{
switch (transportMethod)
{
case "Bicycle":
return (decimal)(DistanceToDestination * 1);
case "Bus":
return (decimal)(DistanceToDestination * 2);
case "Car":
return (decimal)(DistanceToDestination * 3);
default:
throw new ArgumentOutOfRangeException();
}
}
This is fine and all, but switch cases can be a nightmare to maintenance wise, and what if I want to use airplane or train later on? Then I have to change the above class. What alternative to a switch case could I use here and any hints to how?
I'm imagining using it in a console application like this which would be run from the command-line with arguments for what kind of transportation vehicle you want to use, and the distance you want to travel:
class Program
{
static void Main(string[] args)
{
if(args.Length < 2)
{
Console.WriteLine("Not enough arguments to run this program");
Console.ReadLine();
}
else
{
var transportMethod = args[0];
var distance = args[1];
var calculator = new TransportCostCalculator { DistanceToDestination = double.Parse(distance) };
var result = calculator.CostOfTravel(transportMethod);
Console.WriteLine(result);
Console.ReadLine();
}
}
}
Any hints greatly appreciated!
You could do something like this:
public class TransportationCostCalculator {
Dictionary<string,double> _travelModifier;
TransportationCostCalculator()
{
_travelModifier = new Dictionary<string,double> ();
_travelModifier.Add("bicycle", 1);
_travelModifier.Add("bus", 2);
_travelModifier.Add("car", 3);
}
public decimal CostOfTravel(string transportationMethod) =>
(decimal) _travelModifier[transportationMethod] * DistanceToDestination;
}
You could then load the transportation type and it's modifier in a configuration file instead of using a switch statement. I put it in the constructor to show the example, but it could be loaded from anywhere. I would also probably make the Dictionary static and only load it once. There is no need to keep populating it each time you create a new TransportationCostCalculator especially if it isn't going to change during runtime.
As noted above, here is how you could load it by a configuration file:
void Main()
{
// By Hard coding.
/*
TransportationCostCalculator.AddTravelModifier("bicycle", 1);
TransportationCostCalculator.AddTravelModifier("bus", 2);
TransportationCostCalculator.AddTravelModifier("car", 3);
*/
//By File
//assuming file is: name,value
System.IO.File.ReadAllLines("C:\\temp\\modifiers.txt")
.ToList().ForEach(line =>
{
var parts = line.Split(',');
TransportationCostCalculator.AddTravelModifier
(parts[0], Double.Parse(parts[1]));
}
);
}
public class TransportationCostCalculator {
static Dictionary<string,double> _travelModifier =
new Dictionary<string,double> ();
public static void AddTravelModifier(string name, double modifier)
{
if (_travelModifier.ContainsKey(name))
{
throw new Exception($"{name} already exists in dictionary.");
}
_travelModifier.Add(name, modifier);
}
public double DistanceToDestination { get; set; }
TransportationCostCalculator()
{
_travelModifier = new Dictionary<string,double> ();
}
public decimal CostOfTravel(string transportationMethod) =>
(decimal)( _travelModifier[transportationMethod] * DistanceToDestination);
}
Edit: It was mentioned in the comments that this wouldn't allow the equation to be modified if it ever needed to change without updating the code, so I wrote up a post about how to do it here: https://kemiller2002.github.io/2016/03/07/Configuring-Logic.html.
It looks to me like any solution based on your current method is flawed in one critical way: No matter how you slice it, you're putting data in your code. This means every time you want to change any of these numbers, add a new vehicle type, etc., you have to edit code, and then recompile, distribute a patch, etc.
What you really should be doing is putting that data where it belongs - in a separate, non-compiled file. You can use XML, JSON, some form of database, or even just a simple config file. Encrypt it if you want, not necessarily needed.
Then you'd simply write a parser that reads the file and creates a map of vehicle type to cost multiplier or whatever other properties you want to save. Adding a new vehicle would be as simple as updating your data file. No need edit code or recompile, etc. Much more robust and easier to maintain if you plan to add stuff in the future.
Sounds like a good candidate for dependency-injection:
interface ITransportation {
decimal CalcCosts(double distance);
}
class Bus : ITransportation {
decimal CalcCosts(double distance) { return (decimal)(distance * 2); }
}
class Bicycle : ITransportation {
decimal CalcCosts(double distance) { return (decimal)(distance * 1); }
}
class Car: ITransportation {
decimal CalcCosts(double distance) { return (decimal)(distance * 3); }
}
Now you can easily create a new class Plane:
class Plane : ITransportation {
decimal CalcCosts(double distance) { return (decimal)(distance * 4); }
}
Now create a constrcutor for your calculator that expects an instance of ITransportation. Within your CostOfTravel-method you can now call ITransportation.CalcCosts(DistanceToDestination).
var calculator = new TransportationCostCalculator(new Plane());
This has the advantage that you can exchange your actual transportation-instance without any code-change to your TransportationCostCalculator-class.
To complete this design you might also create a TransportationFactory as follows:
class TransportationFactory {
ITransportation Create(string type) {
switch case "Bus": return new Bus(); break
// ...
}
Which you call like
ITransportation t = myFactory.Create("Bus");
TransportationCostCalculator calculator = new TransportationCostCalculator(t);
var result = myCalculator.CostOfTravel(50);
You could define an abstract class like this, and have each TransportationMethod extend the abstract class:
abstract class TransportationMethod {
public TransportationMethod() {
// constructor logic
}
abstract public double travelCost(double distance);
}
class Bicycle : TransportationMethod {
public Bicycle() : base() { }
override public double travelCost(double distance) {
return distance * 1;
}
}
class Bus : TransportationMethod {
public Bus() : base() { }
override public double travelCost(double distance) {
return distance * 2;
}
}
class Car : TransportationMethod {
public Car() : base() { }
override public double travelCost(double distance) {
return distance * 3;
}
}
So in your actual method call, it could be rewritten like this:
public decimal CostOfTravel(TransportationMethod t) {
return t.travelCost(DistanceToDestination);
}
You could use a strategy class for each type of travel. But, then you'd probably need a factory to create the strategy based upon the transport method which would likely have a switch statement to return the appropriate calculator.
public class CalculatorFactory {
public static ICalculator CreateCalculator(string transportType) {
switch (transportType) {
case "car":
return new CarCalculator();
...
public class CarCalculator : ICalculator {
public decimal Calc(double distance) {
return distance * 1;
}
}
....
You can make a Dictionary that returns a multiplier based on transport.
public class TransportationCostCalculator
{
Dictionary<string, int> multiplierDictionary;
TransportationCostCalculator ()
{
var multiplierDictionary= new Dictionary<string, int> ();
dictionary.Add ("Bicycle", 1);
dictionary.Add ("Bus", 2);
....
}
public decimal CostOfTravel(string transportMethod)
{
return (decimal) (multiplierDictionary[transportMethod] * DistanceToDestination);
}
I think the answer is some kind of database.
If you use some, the TransportCostCalculator ask the database for the multiplayer to the given transportmethod.
The database may be a text-file or an xml or an SQL-server. Simply a key-value-pair.
If you want to use code-only there is - tmo - no way to avoid the translation from transportmethod to multiplayer (or cost). So some kind of swicht is needed.
With the database you put the dictionary out of your code and you must not change your code to apply new transportmethods or change the values.
This is a case for the strategy design pattern. Create a base class, say TravelCostCalculator, then develop classes for each mode of travel you will consider, each overriding a common method, Calculate(double). You can then instantiate the specific TravelCostCalculator as needed using the factory pattern.
The trick is in how to construct the factory (without a switch statement). The way I do this is by having a static class constructor (public static Classname() - not an instance constructor) that registers each strategy class with the factory in a Dictionary<string, Type>.
Since C# does not run class constructors deterministically (like C++ does in most cases) you have to explicitly run them to ensure they will run. This could be done in the main program or in the factory constructor. The downside is that if you add a strategy class, you must also add it to the list of constructors to be run. You can either create a static method that must be run (Touch or Register) or you can also use System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor.
class Derived : Base
{
public static Derived()
{
Factory.Register(typeof(Derived));
}
}
// this could also be done with generics rather than Type class
class Factory
{
public static Register(Type t)
{
RegisteredTypes[t.Name] = t;
}
protected Dictionary<string, Type t> RegisteredTypes;
public static Base Instantiate(string typeName)
{
if (!RegisteredTypes.ContainsKey(typeName))
return null;
return (Base) Activator.CreateInstance(RegisteredTypes[typeName]);
}
}
I prefer to use Enum for that like this:
public enum TransportMethod
{
Bicycle = 1,
Bus = 2,
Car = 3
}
And use it like this method:
public decimal CostOfTravel(string transportMethod)
{
var tmValue = (int)Enum.Parse(typeof(TransportMethod), transportMethod);
return DistanceToDestination * tmValue;
}
Note that above method is case-sensitive, So you can capitalize first char;
Related Answer
It was said before but i want to give related topic another shot.
This is a good example for reflection.
"Reflection objects are used for obtaining type information at runtime. The classes that give access to the metadata of a running program are in the System.Reflection namespace."
By using reflection, you will avoid compiling code if another switch type such as train is wanted to add the program. You will solve the problem on the fly by using a config file.
I recently solved a similar problem with strategy patttern, by using dependency injection but I still end up with switch statement. It doesnt solve your problem this way. Method suggested by tyson still needs recompile if a new type added to dictionary.
An example of what i am talking about:
Dynamic Loading of Custom Configuration XML using Reflection in C# :
http://technico.qnownow.com/dynamic-loading-of-custom-configuration-xml-using-reflection-in-c/
Define a look up table array 3 by 2.
Look up rate value in array cell adjacent to transport type.
Calculate cost based on rate.

Multiple functions with different parameters in c#

I would like to request what's the best way to handle the situation below.
I would like to call populate function for different instance with different parameters. I implemented populate function in each inheritance classes. But I don't know what's the best way to use it for hundreds of times.
(Eg index would be the total number of country in the world).
public enum TCountry
{
tAustralia,
tUnitedKingdom,
.. etc..
}
public enum TCity
{
tSydney,
tLondon,
... etc..
}
public int ProcessData ( string population, int index)
{
switch (index)
{
case 0:
TypeAust aus = new TypeAust();
retun aus.poulate( population, tAustralia, tSydney);
// Different calculation Sydney -Aus
DisplayAus(); // Display for Sydney - Aus
case 1:
TypeUK uk = new TypeUK();
retun uk.poulate( population, tUnitedKingdom, tLondon);
// Different calculation for Londond - UK
DisplayUK(); // Display for London - UK
....
... etc..
}
}
Thanks in Advance
I would recommend going with a different design. Rather than working with that case statement, put all your types in a collection and call populate without knowing what specific type you're working with.
List<TypeCountry> countries = new List<TypeCountry>() { new TypeUK(), TypeAus(), TypeUS() //ect };
//use this list all throughout the program
Instead of you switch statement you can just do;
return countries[index].populate( //args go here );
Then you can do other things like;
int worldPop = countries.Aggregate((c, n) => c.Populate(//args) + n.Populate(//args));
In general you need to stop treating each type as if it's different from the next. Move your logic into the base class, get rid of code that has to refer to the type by name or requires specific checks for which inheriting type it is. For almost all cases you should be able to have a collection of the base classes type and pass it around and work on it without ever knowing what type the specific instance you're dealing with is. If that's not the case then you're doing inheritance wrong. If you have that big case statement then there is no point in even using inheritance because as far as I can tell you're not getting any of it's benefits.
I would have to see more of your actual needs and architecture but you could look into generics.
public int ProcessData<T>(string population) where T : BaseCountry, new() {
var country = new T();
Display(country);
return country.Populate(population);
}
public void Display<T>(T country) where T : BaseCountry { ... }
You would use ProcessData like:
ProcessData<TypeAust>(99);
Your display method would be generic too. This way, your process data method is always constrained to work with anything that implements BaseCountry. BaseCountry would define an abstract or virtual Populate() method.
You could do something like this so the logic is broken out into different classes:
public enum TCountry
{
tAustralia,
tUnitedKingdom
}
public enum TCity
{
tSydney,
tLondon
}
public abstract class TypeCountry
{
public abstract int Populate(string population);
}
public class TypeAust : TypeCountry
{
public override int Populate(string population)
{
// do your calculation with tAustralia, tSydney...
}
}
public class TypeUK: TypeCountry
{
public override int Populate(string population)
{
// do your calculation with tUnitedKingdom, tLondon...
}
}
public static class TypeCountryFactory
{
public static TypeCountry GetCountry(TCountry country)
{
switch (country)
{
case TCountry.tAustralia:
return new TypeAust();
case TCountry.tUnitedKingdom:
return new TypeUK();
}
}
}
public int ProcessData (string population, int TCountry)
{
TypeCountry country = TypeCountryFactory.GetCountry(TCountry);
return country.Populate(population);
}

Automating an object repository for a game

Hello guys i am having trouble designing an object repository for a game:
class ObjectRepository
{
private readonly LevelType _levelType;
private readonly BaseObject[] _darkForestObjects = new BaseObject[]
{ new DarkForestTreeA(), new DarkForestTreeB(), new DarkForestTreeC() };
private readonly BaseObject[] _lightForestObjects = new BaseObject[]
{ new LightForestTreeA(), new LightForestTreeB(), new LightForestTreeC() };
public ObjectRepository(LevelType lt)
{
_levelType = lt;
}
public BaseObject GetObject(int obj)
{
if (obj < 0 || obj > _darkForestObjects.Length)
{
Debug.LogError("Object does not exist.");
return null;
}
switch (_levelType)
{
case LevelType.DarkForest:
return _darkForestObjects[obj];
case LevelType.LightForest:
return _lightForestObjects[obj];
}
return null;
}
}
public enum LevelType
{
DarkForest = 0,
LightForest = 1,
}
I am searching for a way of automating this class.By automating it i mean that i don't want every time i create a new object deriving from BaseObject to come inside the Repository class and modify arrays.It just doesn't seem natural.Can anybody point me out a suggestion for automation?
I'll take a gander at this, so please let me know if I'm assuming things wrong.
You'll need:
A repository that'll hold your BaseObject-derived instances;
Said repository must be accessible by the BaseObject class;
Whenever a BaseObject is created, it adds itself to the repository.
Now, I've noticed that you hold instances for both dark and light versions of your objects. So I'd additionally suggest a holder class for both light and dark versions of a given 'object'. Like this:
class CompoundObject
{
public BaseObject LightVersion;
public BaseObject DarkVersion;
}
Your repository then hold CompoundObject-derived objects, and instead of BaseObject objects adding themselves at creation time, CompoundObject objects would do it.
Now about Array manipulations, you may be right; it can be somewhat clunky. I'd suggest the adoption of List<CompoundObject> instead of CompoundObject[]. A generic List offer very handy methods like Add and Remove that can streamline your collection manipulation.
If I were you, I would opt for a more generic solution using interfaces.
Considering your example, I assume that you have multiple level types which have their own specific TreeA, TreeB and TreeC implementations.
If I understood right, I would rather use interface for each tree type. Example for TreeA :
public interface ITreeA
{
// any common public members here
}
public class DarkForestTreeA : ITreeA, BaseObject
{
...
}
public class LightForestTreeA : ITreeA, BaseObject
{
...
}
This way, you can ask your repository to provide the ITreeA implementation specific to the level type. Something like :
public T GetObject<T>() // where T could be ITreeA, ITreeB...
{
...
}
So you could call myRepo.GetObject() and get a DarkForestTreeA object if level type is DarkForest for example.
To have this behavior "automated", you could declare all the specific implementations of DarkForest in a unique namespace and then use reflexion to find the class of the namespace that implements ITreeA for example. This may not be very efficient in terms of performance but it gives you great flexibility as you will just have to add new classes in your namespace to have them available from the repository. However, it can also bring other problems (for example, what would happen if you have two classes implementing ITreeA in the same namespace ?).
See Getting all types in a namespace via reflection and Getting all types that implement an interface with C# 3.0 for implementation details.
I have to admit it isn't the simplest solution.
You could consider simpler thing like defining a dictionary for object type (treeA, treeB) and then define a dictionary for each level type mapping the object type to its concrete implementation.
For example :
public enum ObjectType
{
TreeA,
TreeB,
TreeC,
}
Dictionary<ObjectType, Type> DarkForestObjectTypes = new Dictionary<ObjectType, Type>()
{
{ ObjectType.TreeA, typeof(DarkForestTreeA) },
{ ObjectType.TreeB, typeof(DarkForestTreeB) }
...
}
I won't go into more details as this answer looks a bit messy but hopefully it will give you ideas to go on with.

What is a good way to setup a form that supports multiple objects with the same base type?

I hava a base type (A) which has two derivatives (B and C). The base type is not abstract. So, I have three objects.
The only difference between B and C is that they both have one extra different property:
B.Foo
C.Bar
Now I have conditions like this in my code:
if(myObject is B)
myDatabindB.DataSource = ((B)myReport).Foo);
else if(myObject is C)
myDatabindC.DataSource = ((C)myReport).Bar);
and in another method:
pnlSomePanel.Visible = myObject is B;
pnlSomeOtherPanel.Visible = myObject is C;
But you can imagine that when there's a new type I have to update all my if-else statements. This violates a lot of OO principles.
But the problem is that I can't think of a nice and clean solution to solve this issue.
Do you have a suggestion / idea to solve this problem?
EDIT:
If it matters, I am using the MVP pattern.
First, it's good that you asked this with only three items--it makes fixing problems much faster :). Your code's very generic, so I can only offer generic solutions.
The big goal here is to increase the encapsulation of classes A, B, and C--to make sure that anything relevant to A, B, or C is stored within those classes and not moved to, say, if-statements elsewhere.
We can move the logic for figuring out what the correct datasource is from the Controller (which is doing your binding) to your report. This method's name should be descriptive, like GetReportSubjectLine().
class A{
<snip>
public virtual SomeDataType getDataSourceForViewType(){
throw new NotImplementedException()
}
}
class B{
<snip>
public override SomeDataType getDataSourceForViewType(){
return this.Foo;
}
}
class C{
public override SomeDataType getDataSourceForViewType(){
return this.Bar;
}
}
This code will be reusable if you ever want to make different UI's that still need this type of information from your report to generate whatever graphical view you're generating.
There's no good way around the second problem you presented. We could always move the panel visibility into the reports too, but that increases coupling--how much one class is tied to another--way too much. Your reports should not be tied to a specific view.
The best solution is to add another layer of indirection--in this case, an intermediary class to handle the logic of what panels to make visible when. This way your controller doesn't have to bear the responsibility of managing panel visibilities itself.
public class PanelVisibilityManager{
ICollection<Panel> ManagedPanels {get; set;}
//
public IDictionary<System.Type, ICollection<Panel>> Switchboard {get; set;}
public void TogglePanelsFor(System.Type item){
foreach(var panel in ManagedPanels){
panel.Visible=false;
}
foreach(var panel in Switchboard[item]){
panel.Visible=true;
}
}
Hope this helps!
Strategy Pattern fits here pretty well for the first case
For the second case if you have one to one mapping of your panels you can end up with a static readonly Dictionary<Type, Panel> panels if there are many of types.
There is a tab control in WinForms to show some particular tab as well
One the ways to avoid that type of code is move decisional responability into object itself. For example:
Define somewher collection of A.
List<A> objects = new List<A>{new B(), new C()}
Instead of having if/else use foreach over collection and calll on every object a virtual method defined in A and overriden in childs, like
virtual bool ThisIsMe(A objectToCheck){}
B and C override this method by checking if objectToCheck is their type and return true or false in regard of it.
EDIT
Example:
public class A
{
public virtual bool ThisIsMe(A objectToCheck){}
public virtual object GetData{}
}
public class B : A
{
public override bool ThisIsMe(A objectToCheck)
{
return objectToCheck is B;
}
public override object GetData()
{
return this.Foo;
}
}
public class C : A
{
public override bool ThisIsMe(A objectToCheck)
{
return objectToCheck is B;
}
public override object GetData()
{
return this.Bar;
}
}
Now instead of that if/else, something like this:
foreach(A objA in objects)
{
if(objA.ThisIsMe(myObject))
{
myDatabindB.DataSource = objA.GetData();
break;
}
}
May be also substitude this with some fancy LINQ instruction.
Hope this helps.
How about a Dictionary<Type, Action>?
Then you could do something like this:
var myActors = new Dictionary<Type, Action<BaseClass>>();
myActors.Add(typeof(classA), DoSomethingWithA);
myActors.Add(typeof(classB), DoSomethingWithB);
...
Action actor;
if(myActors.TryGetValue(specialRetrievedOnlyAsBase.GetType(), actor))
{
ResetEverything();
actor(specialRetrievedOnlyAsBase);
}
else
{
// ToDo: What should happen if this type is not supported?
}
...
private void DoSomethingWithA(BaseClass)
{
var classAObject = (ClassA)BaseClass;
// ToDo: What should happen if classA arrives?
}
private void DoSomethingWithA(BaseClass)
{
var classAObject = (ClassB)BaseClass;
// ToDo: What should happen if classB arrives?
}

Categories

Resources