2 objects are in this project: Region and Area.
Both objects have a method called
void load();
This is what I want to to, not sure if it's possible:
Invoke the same Detail function with similar implementation depending on which object called the function.
The Detail function will do something like this:
void Detail(parameter)
{
object_name.load();
}
I didn't want to write 2 overloaded functions for the each object because then I would have 2 functions with nearly identical implementations.
I have tried:
void Detail(string land)
{
if(land=="region")
{
Region land = new Region();
}
else if(land=="area")
{
Area land = new Area();
}
land.load();
}
But this doesn't work because land.load() will cause an error since the function cannot determine at definition whether land will be a Region or an Area object.
It sounds like you want an interface.
public interface IShape
{
void load();
}
Which both Region and Area would implement:
public class Region : IShape
{
public void load() { /* Region Implementation */ }
}
public class Area : IShape
{
public void load() { /* Area Implementation */ }
}
Your detail function now looks like this:
void Detail(IShape shape)
{
shape.load();
}
Some notes:
Interfaces define a contract without implementation. Your Detail function does not need to know whether it is an Area or a Region provided the class in question adheres to the contract that IShape defines, that is - it has a load() method.
Edit
Looking at your question more closely, it also looks like you want to implement a factory. So let's do that also.
public static class ShapeFactory
{
private static Dictionary<string, Func<IShape>> _shapes = new Dictionary<string, Func<IShape>>();
static ShapeFactory()
{
// Register some creators:
_shapes.Add("region", () => return new Region());
_shapes.Add("area", () => return new Area());
}
public static IShape Create(string shape)
{
return _shapes[shape]();
}
}
This allows your detail function to be rather simple:
void Detail(string shape)
{
ShapeFactory.Create(shape).load();
}
Error checking omitted for brevity. So what does this do? Well, a factory is - well - a factory. We create a dictionary (keyed by name), and whose value is a function that returns an IShape.. we can now dynamically create shapes by name and call the load method on it.
Edit 2
Given your comment that you cannot change what interfaces these classes implement, there's no reason we can't still obfuscate the load method (given that they both implement it). All we have to do is, once again utilise our interface again:
public interface IShapeWrapper
{
void load();
}
Note that our interface is still the same. What is different is the implementations:
public class RegionWrapper : IShapeWrapper
{
private Region _region;
public RegionWrapper()
{
_region = new Region();
}
public void load()
{
_region.load();
}
}
public class AreaWrapper : IShapeWrapper
{
private Area _area;
public AreaWrapper()
{
_area = new Area();
}
public void load()
{
_area.load();
}
}
The factory remains much the same, with the exception that it takes the wrapper classes rather than the Area/Region ones.
You might want to make the classes share an interface, e.g.
public interface ILoad { void Load(); }
public class Area : ILoad { }
public class Region : ILoad { }
void Detail(ILoad land)
{
land.Load();
}
Or maybe use dynamic, e.g.
void Detail(string landStr)
{
dynamic land;
if (landStr == "region")
{
land = new Region();
}
else
{
land = new Area();
}
land.load();
}
There are several ways of addressing this. A simple way would be giving both Area and Region classes an ILoadable interface to implement, like this:
interface ILoadable {
void load();
}
class Area : ILoadable {
public void load() {...}
}
class Region : ILoadable {
public void load() {...}
}
Now you can change your Detail method as follows:
void Detail(string land) {
ILoadable loadable;
if(land=="region") {
loadable = new Region();
} else if(land=="area") {
loadable = new Area();
} else {
throw new InvalidOperationException(land);
}
loadable.load();
}
If you would like to make Detail a generic function, you can get rid of the string land parameter, and pass the class directly:
void Detail<T>() where T : ILoadable, new() {
new T().load();
}
You can call this function like this:
Detail<Region>();
Detail<Area>();
Going the interface way is quite a possibility, or creating a full fledged Factory also, but it might be overkill depending on your need.
If you expect to have a lot more functions like load(), do it the way other have said, but if not, or if you cannot change what class they inherit like you stated, here is another way of doing it simply and quickly using dynamics:
void Detail(string land)
{
dynamic land = null;
if (land == "region")
{
land = new Region();
}
else if (land == "area")
{
land = new Area();
}
else
{
// Not what we expected
throw new ArgumentException("land: " + land);
}
try
{
land.load();
}
catch (RuntimeBinderException ex)
{
// .load() does not exist
}
}
Related
I just started to learn Decorator Design Pattern, unfortunately i had to go through various refrences to understand the Decorator pattern in a better manner which led me in great confusion. so, as far as my understanding is concern, i believe this is a decorator pattern
interface IComponent
{
void Operation();
}
class Component : IComponent
{
public void Operation()
{
Console.WriteLine("I am walking ");
}
}
class DecoratorA : IComponent
{
IComponent component;
public DecoratorA(IComponent c)
{
component = c;
}
public void Operation()
{
component.Operation();
Console.WriteLine("in the rain");
}
}
class DecoratorB : IComponent
{
IComponent component;
public DecoratorB(IComponent c)
{
component = c;
}
public void Operation()
{
component.Operation();
Console.WriteLine("with an umbrella");
}
}
class Client
{
static void Main()
{
IComponent component = new Component();
component.Operation();
DecoratorA decoratorA = new DecoratorA(new Component());
component.Operation();
DecoratorB decoratorB = new DecoratorB(new Component());
component.Operation();
Console.Read();
}
}
But can the below code also be Decorator Pattern?
class Photo
{
public void Draw()
{
Console.WriteLine("draw a photo");
}
}
class BorderedPhoto : Photo
{
public void drawBorder()
{
Console.WriteLine("draw a border photo");
}
}
class FramePhoto : BorderedPhoto
{
public void frame()
{
Console.WriteLine("frame the photo");
}
}
class Client
{
static void Main()
{
Photo p = new Photo();
p.Draw();
BorderedPhoto b = new BorderedPhoto();
b.Draw();
b.drawBorder();
FramePhoto f = new FramePhoto();
f.Draw();
f.drawBorder();
f.frame();
}
}
My Understanding
From the second example given by me, we can call all the three methods, but from the first example i wont be able to get access to all the three methods by creating a single object.
It should be a comment, but I have too many words.
For example, you have an object and interface, like Repository : IRepository.
public interface IRepository
{
void SaveStuff();
}
public class Repository : IRepository
{
public void SaveStuff()
{
// save stuff
}
}
and client, which probably was written by someone else
class RepoClient
{
public void DoSomething(IRepository repo)
{
//...
repo.SaveStuff();
}
}
And once you decided, that ALL calls to repository should be logged. But you have a problem: the Repository class is from an external library and you don't want to change that code. So you need to extend the Repository's behavior that you use. You write RepositoryLogDecorator : IRepository, and inside on each method do the logging, like
public class RepositoryLogDecorator : IRepository
{
public IRepository _inner;
public RepositoryLogDecorator(IRepository inner)
{
_inner = inner;
}
public void SaveStuff()
{
// log enter to method
try
{
_inner.SaveStuff();
}
catch(Exception ex)
{
// log exception
}
// log exit to method
}
}
So, before you could use client as
var client = new RepoClient();
client.DoSomething(new Repository());
but now you can use
var client = new RepoClient();
client.DoSomething(new RepositoryLogDecorator(new Repository()));
Note, that this is a very simple example. In real projects, where object created primary with DI container, you will be able to use decorator by changing some config.
So, decorator is used to extend functionality of object without changing object or client.
Another benefit of decorator: your decorator does not depend on Repository implementation. Only depends from an interface IRepository. Why this is an advantage? If somehow you decide to write you own implementation of IRepository
public class MyAwesomeRepository : IRepository
{
public void SaveStuff()
{
// save stuff, but AWESOME!
}
}
you will be able to automatically decorate this with decorator, which already exist
var client = new RepoClient();
client.DoSomethig(new RepositoryLogDecorator(new MyAwesomeRepository()));
Want to see example from real software? (just as sample, code is ugly, I know) => go here
There is this PatternCraft series on Youtube that explains Design Patterns with Starcraft, you should check the video about Decorators here.
In the video above the author gives an example with a Marine and WeaponUpgrade.
In the game you will have a Marine and then you can upgrade its weapon:
marine = new WeaponUpgrade(marine);
Note that you still have a marine there, it is not a new unit, it is the same unit with things that modifies its attributes.
public class MarineWeaponUpgrade : IMarine
{
private IMarine marine;
public MarineWeaponUpgrade(IMarine marine)
{
this.marine = marine;
}
public int Damage
{
get { return this.marine.Damage + 1; } // here
set { this.marine.Damage = value; }
}
}
You do that by creating a class that implements the same interface as your unit and access your unit properties to modify values.
There is a Kata on CodeWars challenging you to complete the Weapon and Armor decorators for a marine.
Per GOF page Decorator desing pattern:
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
In your second example you are using inheritance to extend behaviour of a class, I believe this is technically not a Decorator design pattern.
The decorator pattern allows you to add a specific behavior to an individual object of a given type without affecting other instances of that same type.
In your second example, which is normal inheritance, all instances of the class inherit the modified behavior.
The second example is not a decorate pattern, since an essential ingredient to decorator pattern is that the object accepts one of its kind and possibly enhance it.
An instances of this in the first example is
public DecoratorA(IComponent c)
{
component = c;
}
Also, the goal of the decorator pattern is to create "one" object, then decorate it by passing it through different filters or decorators.
Hence the line
DecoratorA decoratorA = new DecoratorA(new Component());
Should be
DecoratorA decoratorA = new DecoratorA(component );
I've been having trouble even defining what I am looking for.
I am writing an app to determine winners in a tournament. I would like my base class to be able to change it's inheritance based on how many people are playing, given that multiple inheritance is not an option, and probably wouldn't be a very good one the more i think on it.
I see something along the lines of
class Base
{
//Constructor receiving the quantity of players
public Base (int quantityOfPlayers)
{
//Changes Base inheritance dynamically based on QuantityOfPlayers
switch (quantityOfPlayers)
{
case 4: (Base : FourPlayers);
case 5: (Base : FivePlayers);
}
}
}
But of course i can't seem to find a means (if there is one) of dynamically changing the inheritance like that. Otherwise I'm stuck using more complicated means though each of the getter and setter functions are going to be essentially the same.
Very good solutions. let me add that I'm using a GUI not the console.
I have to think on this, the factory class is good, but it has convinced me I'm over thinking my approach.
There is a software design pattern called strategy pattern for this kind of situation.
Define an interface for the game strategy
public interface IGameStrategy
{
// Things that depend on the number of players, go here...
}
The right strategy gets injected into the game through constructor injection
public class Game
{
private IGameStrategy _strategy;
// Constructor injection
public Game(IGameStrategy strategy)
{
_strategy = strategy;
}
// Things common to all types of games go here...
}
Define a factory method like this:
private IGameStrategy CreateGameStrategy(int numberOfPlayers)
switch (numberOfPlayers)
{
case 4:
return FourPlayersStrategy();
case 5:
return FivePlayersStrategy();
default:
throw new ArgumentException("Invalid number of players");
}
}
Then create a game like this:
var game = new Game(CreateGameStrategy(numberOfPlayers));
Of course the strategy classes implement the interface. They can do so directly or they can inherit a common abstract base class implementing the interface.
The game logic is split into things common to all types of games implemented in the Game class and things specific to the number of players implemented in the strategy classes.
You could create a factory class that generates the proper class based on the number of players:
public class PlayerQtyFactory
{
//You can add any other args you might need as well
public BaseClass CreatePlayerQty(int numPlayers)
{
switch (numPlayers)
{
Case 2:
return new TwoPlayers();
Case 3:
return new ThreePlayers();
{
}
}
Without knowing more about what you are trying to do, it is hard to say if this is the best approach, but it is certainly A aproach.
For this particular situation I would use a factoryesque (or just plan factory) solution
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tester
{
//declare common functionality
public interface ISharedFunctionality
{
//put all shared functionality here
void SomeMethod();
void SomeOtherMethod();
void DifferentMethod();
string Name {get;set;}
}
public interface ISinglePlayerFunctionality : ISharedFunctionality
{
//put single player functionality here
void SomeOtherMethod();
void SomeMethod();
}
public interface IMultiplePlayerFunctionality : ISharedFunctionality
{
//put multiplayer functionality here
void DifferentMethod();
void SomeMethod();
}
public class ImplementationBase : ISharedFunctionality
{
//shared implementation here
public void SomeMethod()
{
//do stuff
Console.WriteLine("In Base");
}
public void SomeOtherMethod()
{
//one you don't want to inherit in multiplayer
Console.WriteLine("In Base");
}
public void DifferentMethod()
{
Console.WriteLine("In Base");
}
public string Name
{
get;
set;
}
}
public class MultiPlayerImplementation : ImplementationBase, IMultiplePlayerFunctionality
{
//multiplay impl
// you inherit some method but don't want to inherit
//SomeOtherMethod when cast to ISharedFunctionality
void ISharedFunctionality.SomeMethod()
{
//when cast to ISharedFunctionality this method will execute not inherited
Console.WriteLine("In MutilPlayImplementation");
}
}
public class SinglePlayerImplementation : ImplementationBase , ISinglePlayerFunctionality
{
//singleplay impl
void ISharedFunctionality.SomeOtherMethod()
{
Console.WriteLine("In SinglePlayerImplementation" );
}
}
public class Factory
{
//logic to decide impl here
public ISharedFunctionality Create(int numberOfPlayer)
{
if (numberOfPlayer == 1)
{
return new SinglePlayerImplementation();
}
else if(numberOfPlayer > 1)
{
return new MultiPlayerImplementation();
}
return null;
}
}
class Program
{
static void Main(string[] args)
{
var factory = new Factory();
var results = new[]{factory.Create(1) , factory.Create(2) };
int j=0;
foreach (var i in results)
{
///for single player will be base
///multiplaryer will be mutliplayer
i.SomeMethod();
//for single player will be single player
// for multiplayer will be base
i.SomeOtherMethod();
i.DifferentMethod();
i.Name = "Item-Number-" + j;
Console.WriteLine();
}
}
}
}
The benefit to this is two fold, you now no longer have ambiguity in terms of what method is being called, and you have a unified place to construct future implementations based off of similair contracts (i.e. three player behavior, different menu behavior, and it might be even less code if you want the exact same methods to just behave differently
I have a directory full of classes, and they basically all look like this:
class QEDestroy {
void showSettings() {
// Do Something Here
}
}
I then have a class that will instantiate one of the classes based on an item that the user selects:
public class QESettings {
public void GetSettings() {
if (QEActions.actionInt >= 0) {
string action = QEActions.actions[QEActions.actionInt];
// Generate the class based on the action.
// Run showSettings() within the class.
}
}
}
What I can't figure out is how to instantiate the class; for example QEDestroy. From what I have read this is how the class is created:
var myObj = Activator.CreateInstance("", "QE" + action);
If so, how do I run the method showSettings()?
The simplest solution is often the correct one. Create an interface.
public interface QE
{
void showSettings();
}
Then have different "versions" of QE that perform different tasks on the showSettings() function.
public class QE_Example
{
public void override showSettings()
{
print("I am different.");
}
}
Then when you instantiate in your QESettings class you do it like this:
public void GetSettings()
{
if(QEActions.actionInt >= 0)
{
...
QE q = new QE_Example();
q.showSettings();
}
}
This means you have actually stumbled upon a well known Design Pattern named Strategy Pattern.
I am programming a game as an exercise and I've run into a design problem. My role playing game will have the typical classes like Fighter, Wizard, Theif, Cleric. How do I design my classes so that players can multi-class? For example, one player might start off as a Fighter (and gain the related skills fighters have), then multi-class to a Wizard (at that point they gain wizard spells), and later on multi-class yet again to a rogue (now gaining all abilities rogues have). So this player is now a Fighter-Wizard-Rogue. I don't know to represent this in C#.
At first I tried to use the decorator pattern but I'm unable to multi-class multiple times with this. Any pointers on how to design this?
Only thing I can think of is having an IList<CharacterBaseClass> property for each character and adding Fighter, Wizard, Rogue, etc to this as the player multi-classes. So something like this..
class CharacterBaseClass
{
public IList<CharacterBaseClass> MultiClasses { get; set; }
// constructors, etc
}
and each time they mutli-class I add to the IList
// player starts off as Fighter
Warrior player1 = new Warrior();
// now multi-class to Wizard
player1.MultiClasses.Add(new Wizard());
// now multi-class to Theif
player1.MultiClasses.Add(new Theif());
I'm sure there must be a better way than this?
Just because your characters are wizards and warriors, that doesn't mean you have to create subclasses for them. Instead, ask yourself, "At the code level, what does a character's class do?" Likely, you won't want to have C# subclasses for character classes at all. Instead, figure out what the class actually does, and then determine the right way to model that in code.
For example, if character class restricts the equiment a character can use, then you can define a class for AllowedEquipment:
public class AllowedEquipment
{
public static AllowedEquiment Warrior()
{
return new AllowedEquipment() {
Daggers = true;
Swords = true;
Shields = true;
Armor = true
};
}
public static AllowedEquiment Wizard()
{
return new AllowedEquipment() {
Daggers = true;
Swords = false;
Shields = false;
Armor = true
};
}
public bool Daggers { get; set; }
public bool Swords { get; set; }
public bool Shields { get; set; }
public bool Armor { get; set; }
}
Don't feel you need to use subclasses to model every "is-a" relationship in your game.
Another option is to use the Type Object pattern to model your character classes. If you do that, it'd be easy to give each character a set of those Type Object instances instead of a single one, giving you, in effect, multiple inheritance.
With the decorator pattern, you could possibly do it.
Character person = new Character("Rambo");
person = new Fighter(person); // decorate him with Fighter skills
person = new Thief(person); // also decorate him with Thief skills
Personally I would probably look at attaching classes to the character instead:
Character person = new Character("Rambo");
person.AttachClass(new Fighter());
person.AttachClass(new Thief());
Of course, if you need complex interactions between the classes, so that not only does a Fighter/Thief gets bonuses and skills from each, but he gets something more as well, perhaps the only correct route for that might be to create specific multi-classes for all the combinations:
Character person = new Character("Rambo");
person.AttachClass(new FighterThief());
This would of course just explode with all the combinations.
What about a pure table-driven effort?
Place all applicable skills, spells, bonuses, effects, etc. in a hunking big table, then define the classes by linking a specific class to the specific items in that table. This way it would be much simpler to create hybrid classes by linking across different base classes.
To use a decorator pattern and still get proper access to everything, each class (in the programming sense of the word) needs to be implemented properly as a decorator class.
For instance:
public class BaseClass
{
protected BaseClass(BaseClass underlyingCharacterClass);
public abstract bool CanCastSpells();
public abstract List<Spell> GetAvailableSpells();
protected BaseClass UnderlyingCharacterClass;
}
public class Wizard : BaseClass
{
public override bool CanCastSpells() { return true; }
public override List<Spell> GetAvailableSpells()
{
List<Spell> result = new List<Spell>();
if (UnderlyingCharacterClass != null)
result.AddRange(UnderlyingCharacterClass.GetAvailableSpells());
result.Add(new WizardSpell1());
...
return result;
}
}
public class Thief : BaseClass
{
public override bool CanCastSpells()
{
if (UnderlyingCharacterClass != null)
return UnderlyingCharacterClass.CanCastSpells();
return false;
}
public override List<Spell> GetAvailableSpells()
{
List<Spell> result = new List<Spell>();
if (UnderlyingCharacterClass != null)
result.AddRange(UnderlyingCharacterClass.GetAvailableSpells());
return result;
}
}
If the classes have some common interface or base class, then multiclass is additional class (MultiClass) which also implements this interface or base class, then delegates to its contained instances.
For example:
public class MultiClass : Class {
...
public MultiClass(params Class[] classes) {
this.classes = classes;
}
public IEnumerable<Ability> GetAbilities() {
return this.classes.SelectMany(с => c.GetAbilities());
}
...
}
If you want to add more classes, you can add AddClass method to the base Class, which would create MultiClass from single class, or recreate multiclass with one more contained class for MultiClass.
Not everyone's cup of tea, but you could use state pattern.
public interface Player
{
void Fight();
void CastSpell();
void DoRoguishThings();
}
public class PlayerImpl : Player
{
Player fighter;
Player wizard;
Player rogue;
Player current;
public void Fight(){ current.Fight(); }
public void CastSpell(){ current.CastSpell(); }
public void DoRoguishThings(){ current.DoRoguishThings; }
public void MakeWizard(){ current = wizard; }
public void GoRogue(){ current = rogue; }
}
public class Fighter : Player
{
public void Fight(){ // do fighting }
public void CastSpell()
{
Console.WriteLine("You can't cast a spell, you are but a mere pugilist.");
}
...
}
public class Wizard : Player
{
public void Fight(){ // do wizardly fighting }
public void CastSpell() { // do spell-casting }
public void DoRoguishThings() { // whatever }
}
I think your characters should be able to have multiple Facet/Role implementing "Archetypes".
Then each one having multiple skills or attributes. Let's say...
class Archetype
{
string Name;
Dictionary<string,Type> Properties;
Dictionary<string,Action> Skills;
}
class Character
{
string Name;
string Alias;
Dictionary<Archetype,Dictionary<string,object>> FacetData;
}
class TheGame
{
public static void Main()
{
var Pilot = new Archetype();
Pilot.Name = "Combat-Pilot";
Pilot.Properties.Add("FlightHours", typeof(int));
Pilot.Properties.Add("AmbientTypes", typeof(List<string>));
var Jedi = new Archetype();
Jedi.Name = "Jedi";
Jedi.Properties.Add("ForceLevel", typeof(int));
Jedi.Properties.Add("Title", typeof(string));
Jedi.Properties.Add("IsCombatVeteran", typeof(bool));
Jedi.Skills.Add("LightSaberFight", FightWithLightSaber());
var Anakin = new Character();
Anakin.Id = 100;
Anakin.Name = "Anakin Skywalker";
Anakin.Alias = "Darth Vader";
Anakin.FacetData.Add(Pilot, new Dictionary<string, object>()
{ { "FlightHours", 2500 },
{ "AmbientTypes", new List<string>() {"Atmospheric", "Space", "Hyper-Space"} } };
Anakin.FacetData.Add(Jedi, new Dictionary<string, object>()
{ { "ForceLevel", 7 },
{ "Title", "Padawan" },
{ "IsCombatVeteran", true } };
Anakin.ApplySkill(Jedi, "LightSaberFight", Target);
}
public static void FightWithLightSaber(Character Target)
{
ShowBrightLightSaberPointingTo(Target);
EmitCoolSound();
}
}
If you get the Idea, then you could store properties/data and call skills/tasks with some degree of indirection and flexibility.
Good luck!
You may want to consider composition.
interface IWarrior
{
void Slash();
}
interface IMage
{
void Cast();
}
class Warrior : IWarrior
{
public void Slash() { }
}
class Mage : IMage
{
public void Cast() { }
}
class WarriorMage : IWarrior, IMage
{
private readonly Warrior _Warrior;
private readonly Mage _Mage;
public void Slash()
{
_Warrior.Slash();
}
public void Cast()
{
_Mage.Cast();
}
}
Néstor Sánchez A. provides you with a good solution. Drop your OOP thinking for a while and read this:
http://www.devmaster.net/articles/oo-game-design/
Not every problem can be solved with plain OOP in an elegant way.
I have a class that gets used in a client application and in a server application.
In the server application, I add some functionality to the class trough extension methods. Works great. Now I want a bit more:
My class (B) inherits from another class (A).
I'd like to attach a virtual function to A (let's say Execute() ), and then implement that function in B. But only in the server. The Execute() method would need to do stuff that is only possible to do on the server, using types that only the server knows about.
There are many types that inherit from A just like B does, and I'd like to implement Execute() for each of them.
I was hoping I could add a virtual extension method to A, but that idea doesn't seem to fly. I'm looking for the most elegant way to solve this problem, with or without extension methods.
No, there aren't such things as virtual extension methods. You could use overloading, but that doesn't support polymorphism. It sounds like you might want to look at something like dependency injection (etc) to have different code (dependencies) added in different environments - and use it in regular virtual methods:
class B {
public B(ISomeUtility util) {
// store util
}
public override void Execute() {
if(util != null) util.Foo();
}
}
Then use a DI framework to provide a server-specific ISomeUtility implementation to B at runtime. You can do the same thing with a central static registry (IOC, but no DI):
override void Execute() {
ISomeUtility util = Registry.Get<ISomeUtility>();
if(util != null) util.Foo();
}
(where you'd need to write Registry etc; plus on the server, register the ISomeUtility implementation)
You can use the new dynamic type functionality to avoid having to build a registry of types to methods:
using System;
using System.Collections.Generic;
using System.Linq;
using visitor.Extension;
namespace visitor
{
namespace Extension
{
static class Extension
{
public static void RunVisitor(this IThing thing, IThingOperation thingOperation)
{
thingOperation.Visit((dynamic)thing);
}
public static ITransformedThing GetTransformedThing(this IThing thing, int arg)
{
var x = new GetTransformedThing {Arg = arg};
thing.RunVisitor(x);
return x.Result;
}
}
}
interface IThingOperation
{
void Visit(IThing iThing);
void Visit(AThing aThing);
void Visit(BThing bThing);
void Visit(CThing cThing);
void Visit(DThing dThing);
}
interface ITransformedThing { }
class ATransformedThing : ITransformedThing { public ATransformedThing(AThing aThing, int arg) { } }
class BTransformedThing : ITransformedThing { public BTransformedThing(BThing bThing, int arg) { } }
class CTransformedThing : ITransformedThing { public CTransformedThing(CThing cThing, int arg) { } }
class DTransformedThing : ITransformedThing { public DTransformedThing(DThing dThing, int arg) { } }
class GetTransformedThing : IThingOperation
{
public int Arg { get; set; }
public ITransformedThing Result { get; private set; }
public void Visit(IThing iThing) { Result = null; }
public void Visit(AThing aThing) { Result = new ATransformedThing(aThing, Arg); }
public void Visit(BThing bThing) { Result = new BTransformedThing(bThing, Arg); }
public void Visit(CThing cThing) { Result = new CTransformedThing(cThing, Arg); }
public void Visit(DThing dThing) { Result = new DTransformedThing(dThing, Arg); }
}
interface IThing {}
class Thing : IThing {}
class AThing : Thing {}
class BThing : Thing {}
class CThing : Thing {}
class DThing : Thing {}
class EThing : Thing { }
class Program
{
static void Main(string[] args)
{
var things = new List<IThing> { new AThing(), new BThing(), new CThing(), new DThing(), new EThing() };
var transformedThings = things.Select(thing => thing.GetTransformedThing(4)).Where(transformedThing => transformedThing != null).ToList();
foreach (var transformedThing in transformedThings)
{
Console.WriteLine(transformedThing.GetType().ToString());
}
}
}
}
I would suggest something like the following. This code could be improved by adding support for detecting intermediate class hierarchy types that don't have a dispatch mapping and calling the nearest dispatch method based on the runtime hierarchy. It could also be improved by using reflection to detect overload of ExecuteInteral() and adding them automatically to the dispatch map.
using System;
using System.Collections.Generic;
namespace LanguageTests2
{
public class A { }
public class B : A {}
public class C : B {}
public static class VirtualExtensionMethods
{
private static readonly IDictionary<Type,Action<A>> _dispatchMap
= new Dictionary<Type, Action<A>>();
static VirtualExtensionMethods()
{
_dispatchMap[typeof(A)] = x => ExecuteInternal( (A)x );
_dispatchMap[typeof(B)] = x => ExecuteInternal( (B)x );
_dispatchMap[typeof(C)] = x => ExecuteInternal( (C)x );
}
public static void Execute( this A instance )
{
_dispatchMap[instance.GetType()]( instance );
}
private static void ExecuteInternal( A instance )
{
Console.WriteLine("\nCalled ToString() on: " + instance);
}
private static void ExecuteInternal(B instance)
{
Console.WriteLine( "\nCalled ToString() on: " + instance );
}
private static void ExecuteInternal(C instance)
{
Console.WriteLine("\nCalled ToString() on: " + instance);
}
}
public class VirtualExtensionsTest
{
public static void Main()
{
var instanceA = new A();
var instanceB = new B();
var instanceC = new C();
instanceA.Execute();
instanceB.Execute();
instanceC.Execute();
}
}
}
Virtual implies inheritance in a OOP way and extension methods are "just" static methods that through a bit a syntactic sugar the compiler allows you to pretend to call on an instance of the type of its first parameter. So no, virtual extension methods are out of the question.
Check out the answer by Marc Gravell for a possible solution to your problem.
You can implement a service register. Example (server side):
static IDictionary<Type, IService> serviceRegister;
public void ServerMethod(IBusinessType object)
{
serviceRegister[obect.GetType()].Execute(object);
}
What you need are rather services in your server, which implement server side functionality, instead of extension methods. I wouldn't put to much logic into extension methods.
Let me check: you have a class hierarchy inheriting from A, presumably structured according to your business domain. Then you want to add behaviours depending on where the classes execute. So far you've used extension methods, but now you find you cannot get them to vary with your class hierarchy. What kinds of behaviours are you attaching at the server?
If it's stuff like transaction management and security, policies implemented through dependency injection à la Marc's suggestion should work well. You could also consider implementing the Strategy pattern through delegates and lambdas, for a more limited version of DI. However, what's not clear is how client code currently uses your classes and their extension methods on the server. How dependent are other classes on how you add the server-side functionality? Are they server-side only classes that currently expect to find the extension methods?
In any case, it sounds like you're going to need a careful testability design and testing strategy since you are introducing variation along two simultaneous dimensions (inheritance hierarchy, execution environment). You are using unit testing, I trust? Check that whatever solution you choose (e.g. DI through configuration) interacts well with testing and mocking.