Swap base class at runtime? - c#

I know it had been asked a very long time ago, but no answers were really helpful, C# changed a lot since then and my problem is a bit different.
I'm in an environment that allows custom DLL loading, so people can add their content to the running program, let's say, submodules, but of course it comes at costs of some restrictions.
(Edited the example)
Example, none of this code exists
Public abstract class Car
{
int tires=4;
string color;
public Car(string c){
color = c;
}
}
public class SportCar : Car{
int doors = 3;
int maxspeed=100;
public void changeSpeed(int i){
maxspeed = i;
}
}
public class Ferrari : Car{
string model = "Ferrari";
}
What i want to have after is
public ClassResult{
int tires=4;
string color;
int doors = 3;
int maxspeed=100;
string model = "Ferrari";
public ClassResult(string c){
color = c;
}
public void changeSpeed(int i){
maxspeed = i;
}
}
So i asked for inheritance cause shown like this the problem is solved really easily if you have control over the code and can rewrite it. But i do not.
The only thing i can do is post process it to have the end result.
So changing at runtime the mother class of Ferrari or SportCar in the example would solve it, as it would be a classic inheritance but it might be another way.
Currently how i handle the issue is by discarding one of the child classes, but it's not really satisfying and may lead to other issues.
What exact control i have, is a class over all of those, that contain a collection of added classes. And i call some methodes inside of them that they are all supposed to implement. (That's why they all inherit the same base class)
Hope it's clearer this way.

My suggestion would be to look in the direction of composition instead of inheritance.
Based on your example code, I would suggest the following composition:
(PS. this is just pseudo code to get the point across for composition, I typed it here, there are probably some build errors :p)
public class Car
{
public List<CarModule> Modules;
public InvokeMethod(string methodName)
{
Module moduleWithMethod = Modules.FirstOrDefault(m => m.HasMethod(methodName));
moduleWithMethod.InvokeModuleMethod(methodName);
}
}
public abstract class CarModule
{
protected abstract Dictionary<string,Action> _moduleMethods;
public bool HasMethod(string methodName) => _moduleMethods.Keys.Contains(methodName);
public void InvokeModuleMethod(string methodName)
{
_moduleAction[methodName].Invoke()
}
}
public sealed CarMovement : CarModule
{
int _speed = 5;
const int _maxSpeed = 100;
private Dictionary<string,Action> _moduleMethods =
{
["ToMaxSpeed"] = () => ToMaxSpeed()
}
private void ToMaxSpeed()
{
_speed = maxSpeed;
}
}
public class Test
{
public void TestCase()
{
var speedingCar = new Car();
speedingCar.Modules.Add(new CarMovement());
speedingCar.InvokeMethod("ToMaxSpeed");
}
}
Ofcourse I would not suggest using the Action type as a value for the dictionary, but rather use the command pattern to encapsulate the behaviours. Or something like that. But hopefully this gets you somewhere

Related

Cant access subclass methods of object in Dictionary

I am trying to store objects that are only a subclass of an Abstract Class. However, I can only see the abstract class methods and none of the subclass methods. What have I missed?
Class with Error in:
class CharacterStats
{
private Dictionary<StatType, Stat> playerStats;
//Contructor for new game
public CharacterStats()
{
playerStats = new Dictionary<StatType, Stat>();
//Creates all Stats with default values
playerStats.Add(StatType.STA, new StatSta());
playerStats.Add(StatType.STR, new StatStr());
playerStats.Add(StatType.DEX, new StatDex());
playerStats.Add(StatType.DEF, new StatDef());
}
//Returns the damage reduction in %
public int GetDamageReduction()
{
playerStats[StatType.DEF]. //Missing Methods from StatDef class
//Added to remove error message
return 1;
}
}
Abstract Class:
abstract class Stat
{
protected int pointsAdded;
protected int pointCap;
public Stat() {}
public string TestMethod()
{
return "Working!";
}
}
Subclass:
class StatDef : Stat
{
public StatDef() : base()
{
this.pointsAdded = 0;
this.pointCap = 100;
}
public int ApplyDamageReduction(int dmg)
{
//removed data to read easier
return 1;
}
}
Thanks
The type of the expression playerStats[StatType.DEF] is just Stat. The compiler doesn't know what kind of Stat is stored as the value there.
If it will always be a StatDef, then you should just cast:
var def = (StatDef) playerStats[StatType.DEF];
// Now you can use def.ApplyDamageReduction etc
However, you'll need to cast any time you want to use a stat-specific member. Unless you often want to treat multiple stats in the same way, I'd suggest ditching the dictionary approach and just having separate fields:
class CharacterStats
{
private StatDefence defence;
private StatAttack attack;
private StatStrength strength;
// etc
}
You could easily write a method that allows you to iterate over all the stats for the times where that is useful:
public IReadOnlyList<Stat> GetAllStats() =>
new Stat[] { defence, attack, strength, ... };
But my suspicion is that most of the time you're using the stats, you actually want to know a specific stat. I'd always rather write:
var strength = stats.Attack;
than
var strength = stats[StatType.STR];
even if when I don't need the specific aspects of the strength statistic.

How to get number of concrete classes from factory pattern?

Factory pattern usually creates a base class for the concrete classes and the concrete classes then inherit from that base class. For a lot of applications, we need to know the number of the concrete classes this factory can create. For instance, a factory that creates the typical Shape objects (circle, rectangular, etc.) C# code example below:
public class ShapeFactory
{
public IShape GetShape(int shapeIndex)
{
IShape s = null;
const int color = 1;
const int thickness = 5;
switch (shapeIndex)
{
case 1: s = new Square(color, thickness);
break;
case 2: s = new Triangle(thickness);
break;
case 3: s = new Circle(color);
break;
}
return s;
}
}
The user may want to know how many kinds of shapes are supported by the program. I know 2 ways to do this:
Set the number as a constant in the factory class and make it
visible to public. The drawback is that every time you add a new
Shape, you have to manually increase the number of shapes.
Create a dynamic container (List in C#) that contains all instances
of the concrete objects the factory can create. The advantage is
that it can automatically figure out the number of Shapes it can
create, even if new Shape classes are added. The drawback is
obvious, every kind of Shapes have to be created together with the
Shape requested!
What is the best way to do this? Any best practice on this specific topic?
You could create an Enum that has the constants stored for you.
This also helps helps users by knowing the 'possibilities' by the IDE's auto complete features, plus it prevents the user from entering a number 'out of bounds' such as entering '4' in your example. (Mind you I generally write java... so C# isn't my forte, but you can do 'something' similar to this)
public class ShapeFactory
{
enum PossibleShapes {CIRCLE,
SQUARE,
TRIANGLE, // c# allows you to do this (extra comma) on constructors, not sure about Enums, and helps with reducing 'bad' line changes in git/etc.
};
public IShape GetShape(PossibleShapes whichShape)
{
IShape s = null;
switch (shapeCode)
{
case PossibleShapes.SQUARE : s = new Square(color, thickness);
break;
case PossibleShapes.TRIANGLE: s = new Triangle(thickness);
break;
case PossibleShapes.CIRCLE: s = new Circle(color);
break;
}
return s;
}
}
The "issue" of having to edit the class each time you add a new possibility is moot, because you WILL have to edit this class each time you do that, now you just have to edit the 'PossibleShapes' class too.
(Mind you, I still don't think this is proper usage of the Factory Pattern, because I have no clue where the 'color' and 'thickness' values are coming from, but at least this is better than using reflection)
Here is a Builder Pattern Example that I think does a better example encapsulating your object creation for you. (You could use the Factory Method pattern instead of having different named Methods for each Shape you want to 'get' within the builder)
Plus this allows the user to set the color/thickness themselves easily (can still have defaults, but I didn't put that into this code example)
Represents a product created by the builder
public class Shape
{
public Shape()
{
}
public int Color { get; set; }
public int Thickness { get; set; }
}
The builder abstraction
public interface IShapeBuilder
{
// Adding NotNull attribute to prevent null input argument
void SetColor([NotNull]string colour);
// Adding NotNull attribute to prevent null input argument
void SetThickness([NotNull]int count);
Shape GetShape();
}
Concrete builder implementation
public class ShapeBuilder : IShapeBuilder
{
private Shape _shape;
public ShapeBuilder()
{
}
public int GetNumberShapesPossible()
{
//return some # here
}
public void GetSquare(){
this._shape = new Square();
}
public void GetCircle(){
this._shape = new Circle();
}
public void SetColor(string color)
{
this._shape.Color = color;
}
public void SetThickness(int thickness)
{
this._shape.Thickness = thickness;
}
public Shape Build()
{
return this._shape;
}
}
The director
public class ShapeBuildDirector
{
public Shape Construct()
{
ShapeBuilder builder = new ShapeBuilder();
builder.GetCircle();
builder.SetColour(2);
builder.SetThickness(4);
return builder.GetResult();
}
}
You are going to have to change some code somewhere when you want to add new concrete classes to your library. Unless you plan on bundling the concrete classes as some kind of .dll There is just no way around that. There will have to be some edit to a builder/factory/etc somewhere.
You can store the types of shapes in an array then use Activator to create the instance. This takes care of indexing, count, and simplifies your creation function.
static class ShapeFactory
{
private static readonly Type[] _shapes = new Type[] { typeof(Square), typeof(Triangle), typeof(Circle) };
public static int FactorySize
{
get
{
return _shapes.Length;
}
}
public static IShape GetShape(int shapeIndex, params object[] ctorParams)
{
return (IShape)Activator.CreateInstance(_shapes[shapeIndex], ctorParams);
}
}

Deserializing with DataContract Collection<Class> to derived Class

The title is a bit confusing, hopefully someone maybe know's a better fitting title for my problem.
I am trying to create a class which derives from Collection<Classname> to implement an easy way to save and loading Configuration files. Writing to file is no problem, but I am not able to implement the deserialze function. I am unsure how to assign the deserialized content back to my instance.
Current approach:
[DataContract(Name = "Configurations", Namespace = "")]
public class Configurations : Collection<Configuration>
{
internal void SerializeToBinaryFile(string path)
{
Helper.DumpObjectToBinaryFile(this, path);
}
internal void DeserializeFromBinaryFile(string path)
{
// Getting Error:
// This expression can not be used as an assignment target
this = Helper.GetObjectFromBinaryFile<Collection<Configuration>>(path);
}
}
I am familiar with this.Add([Configuration]) but this just gives the opportunity to insert one item. I thought about using a foreach(Configuration c in temporaryObject and add them one by one but this can't be the best solution.
Thanks for any hint!
Edit 1:
I've added the foreach iteration for adding the Configurations
internal void DeserializeFromBinaryFile(string path)
{
foreach (var c in Helper.GetObjectFromBinaryFile<Collection<Configuration>>(path))
{
Add(c);
}
}
This seems to work fine. Does someone know a better pattern?
You cannot assign to new instance of class to "this" regardless if you are doing de-serialization or something else. Code bellow just uses new constructor and doesn't work either. Basically, you do have different 2 instances of class in memory at that point.
public class Point
{
public int X { get; set; }
public int Y { get; set; }
public void CreatePoint(int x, int y)
{
// Doesn't work either
this = new Point();
}
}
You have to do this outside of the body of the class, so rather make static deserialization method:
[DataContract(Name = "Configurations", Namespace = "")]
public class Configurations : Collection<Configuration>
{
internal void SerializeToBinaryFile(string path)
{
Helper.DumpObjectToBinaryFile(this, path);
}
internal static Configurations DeserializeFromBinaryFile(string path)
{
return Helper.GetObjectFromBinaryFile<Collection<Configuration>>(path);
}
}

Interface inheritance/hierarchies in .Net - is there a better way?

I figure I'll use a case study of something in my code as an example of what I mean.
Right now, I'm working on a behavior/action system for my component-based game system. GameObjects can have an IBehaviorComponent and an IActionComponent attached to them, which, showing only the relevant details, expose the following:
public interface IBehaviorComponent : IBaseComponent
{
IBehavior Behavior { get; }
}
public interface IActionComponent : IBaseComponent
{
IAction Action { get; }
void ExecuteAction(IGameObject target = null);
}
Now, this is all fine so far (at least to me!). But, trouble begins to brew when I look at implementations of IActionComponent.
For example, a simple IActionComponent implementation:
public class SimpleActionComponent : IActionComponent
{
public IAction Action { get; protected set; }
public void ExecuteAction(IGameObject target = null)
{
Action.Execute(target);
}
public void Update(float deltaTime) { } //from IBaseComponent
}
But, let's say I want to introduce a more complex IActionComponent implementation that allows for actions to be executed on a timed schedule:
public class TimedActionComponent : IActionComponent
{
public IAction Action { get; protected set; }
public float IdleTime { get; set; }
public float IdleTimeRemaining { get; protected set; }
public void ExecuteAction(IGameObject target = null)
{
IdleTimeRemaining = IdleTime;
}
public void Update(float deltaTime)
{
if (IdleTimeRemaining > 0f)
{
IdleTimeRemaining -= deltaTime;
}
else
{
Action.Execute(target);
}
}
}
And now, let's say I want to expose IdleTime so that it can be changed by outside influences. My thoughts at first were to create a new interface:
public interface ITimedActionComponent : IActionComponent
{
float IdleTime { get; set; }
float IdleTimeRemaining { get; set; }
}
However, the issue here is that my component system stores everything at one-level-up from IBaseComponent. So, the action component for a GameObject is retrieved as an IActionComponent, -not- as, say, an ITimedActionComponent, or an IRandomizedActionComponent, or even an ICrashTheProgramActionComponent. I hope the reasons for this are obvious, as I want anything to be able to query the GameObject for one of it's components without having to know exactly what it wants beyond the basic type of component (IActionComponent, IRenderableComponent, IPhysicsComponent, etc.)
Is there a cleaner way of handling this, that will allow me to expose these properties defined in child classes without everything having to cast the retrieved IActionComponent to the type it's interested in? Or is that simply the only/best way of accomplishing this. Something like:
public void IWantYouToAttackSuperSlow(IGameObject target)
{
//Let's get the action component for the gameobject and test if it's an ITimedActionComponent...
ITimedActionComponent actionComponent = target.GetComponent<IActionComponent>() as ITimedActionComponent;
if (actionComponent != null) //We're okay!
{
actionComponent.IdleTime = int.MaxValue; //Mwhaha
}
}
Right now I am thinking that's The Only Way, but I figured I'd see if there's a pattern hiding in the woodwork that I'm ignorant of, or if anyone can suggest a much better way of accomplishing this to begin with.
Thanks!
The code you showed that casts-down an IActionComponent to an ITimedActionComponent is (as far as I can see) unavoidable- you have to be aware of the IdleTime properties in order to use them, right?
I think the trick here would be to hide that not-so-nice-looking code where the classes that use your IActionComponent won't have to deal with it.
My first thought on how to do this is to use a Factory:
public void IWantYouToAttackSuperSlow(IGameObject target)
{
//Let's get the action component for the gameobject
IActionComponent actionComponent = ActionComponentsFactory.GetTimedActionComponentIfAvailable(int.MaxValue);
}
and your factory's method:
public IActionComponent GetTimedActionComponentIfAvailable(IGameObject target, int idleTime)
{
var actionComponent = target.GetComponent<IActionComponent>() as ITimedActionComponent;
if (actionComponent != null) //We're okay!
{
actionComponent.IdleTime = int.MaxValue; //Mwhaha
}
return (actionComponent != null)? actionComponent : target.GetComponent<IActionComponent>();
}
You're right, it's not a good idea to test for a specific implementation by casting to subtypes. From the examples you have provided it looks like you have an IGameObject that you want to perform some action on. Rather than having your IActionComponent expose a method that takes the IGameObject as an argument you could sort of do it the other way around, i.e. let the IGameObject take one, or many if you prefer, actions that you can execute.
interface IActionComponent
{
ExecuteAction();
}
interface IGameObject
{
IActionComponent ActionComponent { get; }
}
then in the executing method do
public void IWantYouToAttackSuperSlow(IGameObject target)
{
target.ActionComponent.ExecuteAction();
}
Depending on how you implement IActionComponent, polymorphism will make sure that the right code is executed.
There is a pattern called Command Pattern that seems to fit your need.

Return an opaque object to the caller without violating type-safety

I have a method which should return a snapshot of the current state, and another method which restores that state.
public class MachineModel
{
public Snapshot CurrentSnapshot { get; }
public void RestoreSnapshot (Snapshot saved) { /* etc */ };
}
The state Snapshot class should be completely opaque to the caller--no visible methods or properties--but its properties have to be visible within the MachineModel class. I could obviously do this by downcasting, i.e. have CurrentSnapshot return an object, and have RestoreSnapshot accept an object argument which it casts back to a Snapshot.
But forced casting like that makes me feel dirty. What's the best alternate design that allows me to be both type-safe and opaque?
Update with solution:
I wound up doing a combination of the accepted answer and the suggestion about interfaces. The Snapshot class was made a public abstract class, with a private implementation inside MachineModel:
public class MachineModel
{
public abstract class Snapshot
{
protected internal Snapshot() {}
abstract internal void Restore(MachineModel model);
}
private class SnapshotImpl : Snapshot
{
/* etc */
}
public void Restore(Snapshot state)
{
state.Restore(this);
}
}
Because the constructor and methods of Snapshot are internal, callers from outside the assembly see it as a completely opaque and cannot inherit from it. Callers within the assembly could call Snapshot.Restore rather than MachineModel.Restore, but that's not a big problem. Furthermore, in practice you could never implement Snapshot.Restore without access to MachineModel's private members, which should dissuade people from trying to do so.
Can MachineModel and Snapshot be in the same assembly, and callers in a different assembly? If so, Snapshot could be a public class but with entirely internal members.
I could obviously do this by
downcasting, i.e. have CurrentSnapshot
return an object, and have
RestoreSnapshot accept an object
argument which it casts back to a
Snapshot.
The problem is that somebody could then pass an instance of an object which is not Snapshot.
If you introduce an interface ISnapshot which exposes no methods, and only one implementation exists, you can almost ensure type-safety at the price of a downcast.
I say almost, because you can not completely prevent somebody from creating another implementation of ISnapshot and pass it, which would break. But I feel like that should provide the desired level of information hiding.
You could reverse the dependency and make Snapshot a child (nested class) of MachineModel. Then Snapshot only has a public (or internal) Restore() method which takes as a parameter an instance of MachineModel. Because Snapshot is defined as a child of MachineModel, it can see MachineModel's private fields.
To restore the state, you have two options in the example below. You can call Snapshot.RestoreState(MachineModel) or MachineModel.Restore(Snapshot)*.
public class MachineModel
{
public class Snapshot
{
int _mmPrivateField;
public Snapshot(MachineModel mm)
{
// get mm's state
_mmPrivateField = mm._privateField;
}
public void RestoreState(MachineModel mm)
{
// restore mm's state
mm._privateField = _mmPrivateField;
}
}
int _privateField;
public Snapshot CurrentSnapshot
{
get { return new Snapshot(this); }
}
public void RestoreState(Snapshot ss)
{
ss.Restore(this);
}
}
Example:
MachineModel mm1 = new MachineModel();
MachineModel.Snapshot ss = mm1.CurrentSnapshot;
MachineModel mm2 = new MachineModel();
mm2.RestoreState(ss);
* It would be neater to have Snapshot.RestoreState() as internal and put all callers outside the assembly, so the only way to do a restore is via MachineModel.RestoreState(). But you mentioned on Jon's answer that there will be callers inside the same assembly, so there isn't much point.
This is an old question, but i was looking for something very similar and I ended up here and between the information reported here and some other I came up with this solution, maybe is a little overkill, but this way the state object is fully opaque, even at the assembly level
class Program
{
static void Main(string[] args)
{
DoSomething l_Class = new DoSomething();
Console.WriteLine("Seed: {0}", l_Class.Seed);
Console.WriteLine("Saving State");
DoSomething.SomeState l_State = l_Class.Save_State();
l_Class.Regen_Seed();
Console.WriteLine("Regenerated Seed: {0}", l_Class.Seed);
Console.WriteLine("Restoring State");
l_Class.Restore_State(l_State);
Console.WriteLine("Restored Seed: {0}", l_Class.Seed);
Console.ReadKey();
}
}
class DoSomething
{
static Func<DoSomething, SomeState> g_SomeState_Ctor;
static DoSomething()
{
Type type = typeof(SomeState);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);
}
Random c_Rand = new Random();
public DoSomething()
{
Seed = c_Rand.Next();
}
public SomeState Save_State()
{
return g_SomeState_Ctor(this);
}
public void Restore_State(SomeState f_State)
{
((ISomeState)f_State).Restore_State(this);
}
public void Regen_Seed()
{
Seed = c_Rand.Next();
}
public int Seed { get; private set; }
public class SomeState : ISomeState
{
static SomeState()
{
g_SomeState_Ctor = (DoSomething f_Source) => { return new SomeState(f_Source); };
}
private SomeState(DoSomething f_Source) { Seed = f_Source.Seed; }
void ISomeState.Restore_State(DoSomething f_Source)
{
f_Source.Seed = Seed;
}
int Seed { get; set; }
}
private interface ISomeState
{
void Restore_State(DoSomething f_Source);
}
}

Categories