Make methods work independently without using a common method - c#

I am currently trying to separate out the method implementation so that they can work independently. The methods that I am trying to separate are store and checker. Both these methods require the traverse method. My current implementation has two method store and checker methods which I have separated them into different classes. They require to be called within the traverse method to work. This is the my current implementation.
class Traverse
{
public void traversemethod()
{
Console.WriteLine("Traverse function");
Checker r = new Checker();
r.checkermethod();
Store s = new Store();
s.storemethod();
}
}
class Checker
{
public void checkermethod()
{
Console.WriteLine("Checker function");
}
}
class Store
{
public void storemethod()
{
Console.WriteLine("Store function");
}
}
class Compute
{
public static void Main()
{
Console.WriteLine("Main function");
Traverse v = new Traverse();
v.traversemethod();
Console.ReadLine();
}
Is there any way by which I can implement them separately without declaring them together in traverse method and calling both store and checker method separately in the main function. I can implement the traverse method in both store and checker method, but i was wondering if there is any way to do it rather than duplicating the same code again.

Sounds like a perfect place to use a lambda:
public delegate void TraverseDelegate();
public void traversemethod(TraverseDelegate dlg){
Console.WriteLine("Traverse function");
dlg();
}
and in the Main method use:
Traverse v = new Traverse();
v.traversemethod(() => {
Checker r = new Checker();
r.checkermethod();
Store s = new Store();
s.storemethod();
});
EDIT/UPDATE(=UPDIT :-) )
You can also make the delegate a member field of Traverse, and then pass it as a constructor argument and call traversemethod without any arguments:
public class Traverse{
public delegate void TraverseDelegate();
private TraverseDelegate dlg;
public Traverse(TraverseDelegate dlg){
this.dlg=dlg;
}
public void traversemethod(){
Console.WriteLine("Traverse function");
dlg();
}
}
and in the Main method use:
Traverse v=new Traverse(()=>{
Checker r = new Checker();
r.checkermethod();
Store s = new Store();
s.storemethod();
});
v.traversemethod();

I'm not about the relationship between Checker and Store so I'll show an example with an interface instead of a base class. However you could create a base class, possibly abstract, and have each child class implement their special method.
interface IPerformMethod
{
void SpecialFunction();
}
public class Store : IPerformMethod
{
public void SpecialFunction()
{
Console.WriteLine("Store function");
}
}
public class Checker : IPerformMethod
{
public void SpecialFunction()
{
Console.WriteLine("Checker function");
}
}
Then in your TraverseMethod, you could pass in an object that implements IPerformMethod (in this case it's either an instance of Checker or Store).
public void TraverseMethod(IPerformMethod item)
{
Console.WriteLine("Traverse function");
item.SpecialFunction();
}
//To call the method
TraverseMethod(new Checker());
TraverseMethod(new Store());
(Obviously you can rename the IPerformMethod interface to something more descriptive but if I understand the question correctly, this seems to be what you want).

Related

Hook to function without delegates (Reflection)

Is there a way I could use reflection to hook one function to another without using delegates?
class A
{
void Foo()
{
}
}
class B
{
void Main()
{
A a = new A();
a.GetType().GetMethod("Foo").AddHook(a, Func); //I want something like this
a.Foo();
//Func gets called
}
void Func()
{
}
}
Is there a way to call Func after Foo was called without using events, delegates or just calling Func from inside Foo?
I need this so my game's UI controller can get updated.
The way I see most people dealing with this is by adding a bunch of events to A and subscribing B to those. Like this
class A
{
‎ public delegate void UICallback();
‎ public event UICallback onFoo;
void Foo()
{
‎ onFoo.Invoke();
}
}
class B
{
void Main()
{
A a = new A();
‎a.onFoo += Func;
a.Foo();
}
void Func()
{
}
}
The problem I find with this approach is that I'd need to add a bunch of events like these (probably more than 5 or even 10) to many classes and then remember to invoke those at the end of a function to update UI (invoke onBattleStarted at the end of StartBattle(), for example). This, in addition to increasing the size of my classes with big blocks of event declarations making it ugly to read, makes it a harder maintain.
EDIT I think no one really understands what I'm looking for... I'd like a way to hook Func to Foo without making any changes to Foo, i.e. without Foo knowing this callback exists. Using an action won't help since I'd need specify on Foo's parameters that it should call Func
Thank you for your help!
You Can call Action at the end of Func().
Class A
{
void Foo()
{
}
}
Class B
{
void Main()
{
A a = new A();
Func( () => {a.Foo();});
}
void Func(Action onFinish)
{
//Enter your code here
onFinish();
}
There is the method chaining pattern if that can solve your problem:
namespace Assets
{
public class Example
{
public Example GrabSomeFoodInTheFridge()
{
// some work
return this;
}
public Example WatchTv()
{
// some work
return this;
}
public Example EatFood()
{
// some work
return this;
}
}
public class Demo
{
public Demo()
{
var example = new Example();
var instance = example
.GrabSomeFoodInTheFridge()
.EatFood()
.WatchTv();
}
}
}
It does not use reflection at all, additionally you could leverage interfaces and extension methods.

Refactor long switch statement

I'm program in c# which you controlling by dictating command so now i have a long switch statement. Something like
switch (command)
{
case "Show commands":
ProgramCommans.ShowAllCommands();
break;
case "Close window":
ControlCommands.CloseWindow();
break;
case "Switch window":
ControlCommands.SwitchWindow();
break;
}
and so on
Almost all cases call only one method, methods are not in one class they are distributed in many classes. So the question is, how i could refactor this switch to more elegant way?
You can do this to refactor your switch statement:
var commands = new Dictionary<string, Action>()
{
{ "Show commands", () => ProgramCommans.ShowAllCommands() },
{ "Close window", () => ControlCommands.CloseWindow() },
{ "Switch window", () => ControlCommands.SwitchWindow() },
};
if (commands.ContainsKey(command))
{
commands[command].Invoke();
}
The main advantage to this approach is that you can change the "switch" at run-time.
I much prefer the Strategy Pattern for extending switch case statements. First, I create an interface that defines what each rule should look like:
public interface IWindowRule
{
string Command { get; }
void Invoke();
}
Then create a class that implements the interface for each possible case:
public class ShowAllWindowRule : IWindowRule
{
public string Command => "Show commands";
private ProgramCommands _progCommands;
public ShowAllWindowRule(ProgramCommands programCommands) =>
_progCommands = programCommands;
public void Invoke() => _progCommands.ShowAllCommands();
}
public class CloseWindowRule : IWindowRule
{
private ControlCommands _ctrlCommands;
public string Command => "Close window";
public CloseWindowRule(ControlCommands ctrlCommands) =>
_ctrlCommands = ctrlCommands;
public void Invoke() =>
_ctrlCommands.CloseWindow();
}
public class SwitchWindowRule : IWindowRule
{
private ControlCommands _ctrlCommands;
public string Command => "Switch window";
public SwitchWindowRule(ControlCommands ctrlCommands) =>
_ctrlCommands = ctrlCommands;
public void Invoke() =>
_ctrlCommands.SwitchWindow();
}
Then your switch statement turns into this:
public void RunWindowRule(IList<IWindowRule> rules, string command)
{
foreach (IWindowRule rule in rules)
{
if (rule.Command == command) rule.Invoke();
}
}
Now you can pass the function any set of rules you wish and run them making the function adhere to the Open/Closed principle.
I realize this may appear to be a bit of over engineering, and I do think there are more functional solutions that require a bit less work, however this has the added benefit of allowing you to extend this function by creating classes that inject the list of rules for a myriad of circumstances or even make a builder class that give you a fluent API.
public class WindowRuleBuilder
{
private IList<IWindowRule> rules;
public WindowRuleBuilder(IList<IWindowRule> rules = null) =>
rules = rules ?? new List<IWindowRule>();
public WindowRuleBuilder AddRule(IWindowRule newRule)
{
rules.Add(newRule);
return this;
}
public void Run(string command)
{
foreach (IWindowRule rule in rules)
{
if (rule.Command == command) rule.Invoke();
}
}
}
Now you have something like this:
public static void Main(string[] args)
{
WindowRuleBuilder ruleBuilder = new WindowRuleBuilder()
.AddRule(new CloseWindowRule(conrolCommands))
.AddRule(new ShowAllWindowRule(programCommands))
.AddRule(new SwitchWindowRule(controlCommands));
ruleBuilder.Run(args[0]);
}
This is highly extendable as for ever new rule you simply create the class and add it to the rule builder with the AddRule() method. It also doesn't take much reading to understand what's going on here. It's a much more compositional approach. Though I again admit, it does take a bit of work to implement but the code adheres to SOLID and is finely decoupled.
If all the functions get the same parameters and return the same value, you can use a Dictionary along with delegates to map a string to a function(s). This method will allow you also to change in run time the switch - allowing external programs to extend the functionality of the program.
If the functions aren't the same, you could write wrappers - a proxy function that will get parameters as all other functions, and call the functions you want.
I realize this is an old post, but in these situations I find attributes and a factory very handy.
The following code uses a custom attribute (Command) to allow you to attribute your methods, providing a string value of how they should respond to you.
The factory method uses reflection to generate a dictionary of these methods and calls it whenever you call CommandFactory.
Things could get cleaned up a bit, calling invoke is a little ugly, but it just depends on how you want to execute the code.
using System.Collections.Generic;
using System.Linq;
namespace MyApp
{
using System.Reflection;
using MyApp.Commands;
class Program
{
static void Main(string[] args)
{
var methods = new MyCommands();
MethodInfo myMethod;
myMethod = CommandFactory.GetCommandMethod("Show Commands");
myMethod.Invoke(methods, null);
myMethod = CommandFactory.GetCommandMethod("Close window");
myMethod.Invoke(methods, null);
myMethod = CommandFactory.GetCommandMethod("Switch window");
myMethod.Invoke(methods, null);
}
}
public static class CommandFactory
{
private static Dictionary<string, MethodInfo> speechMethods = new Dictionary<string, MethodInfo>();
public static MethodInfo GetCommandMethod(string commandText)
{
MethodInfo methodInfo;
var commands = new MyCommands();
if (speechMethods.Count == 0)
{
var methodNames =
typeof(MyCommands).GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);
var speechAttributeMethods = methodNames.Where(y => y.GetCustomAttributes().OfType<CommandAttribute>().Any());
foreach (var speechAttributeMethod in speechAttributeMethods)
{
foreach (var attribute in speechAttributeMethod.GetCustomAttributes(true))
{
speechMethods.Add(((CommandAttribute)attribute).Command, speechAttributeMethod);
}
}
methodInfo = speechMethods[commandText];
}
else
{
methodInfo = speechMethods[commandText];
}
return methodInfo;
}
}
}
namespace MyApp.Commands
{
class MyCommands
{
[Command("Show All")]
[Command("Show All Commands")]
[Command("Show commands")]
public void ShowAll()
{
ProgramCommands.ShowAllCommands();
}
[Command("Close Window")]
public void CloseWindow()
{
ControlCommands.CloseWindow();
}
[Command("Switch Window")]
public void SwitchWindow()
{
ControlCommands.SwitchWindow();
}
}
[System.AttributeUsage(System.AttributeTargets.Method, AllowMultiple = true)]
public class CommandAttribute : System.Attribute
{
public string Command
{
get;
set;
}
public CommandAttribute(string textValue)
{
this.Command = textValue;
}
}
}
I know the answer is a bit late, to not abuse the SOLID principle, you may use interface or inheritance. In this example, I use inheritance because u may have other usages of "command" string.
public abstract class commandRepository {
string command ; // if there is no usage in other function class, you can get rid of it
public abstract void DoCommands();
}
public class ShowCommands:commandRepository
{
public ShowCommands (){
command ="Show commands"; // if there is no usage in other function class, you can get rid of it
}
public override void DoCommands(){
ProgramCommans.ShowAllCommands();
}
}
public class CloseWindow:commandRepository
{
public CloseWindow (){
command ="Close window"; // if there is no usage in other function class, you can get rid of it
}
public override void DoCommands(){
ProgramCommans.CloseWindow();
}
}
public class SwitchWindow:commandRepository
{
public SwitchWindow (){
command ="Switch window"; // if there is no usage in other function class, you can get rid of it
}
public override void DoCommands(){
ProgramCommans.SwitchWindow();
}
}
Here's what you can do here. You can create an interface [ICommand] where you can place a common function [eg: Execute].
Then you just needs to initiate that member with appropriate type and call the Execute function. This might include more functions in the future and is thus extended.
Also, you can create a factory method where you can pass the parameter and get the appropriate class to work with.
Hope that helps.

Implementing a double dispatch in C# extensible for both functions and objects to operate on

I'm looking for a way to implement a double dispatch that can be extended for both methods and classes.
Until now I used basically three approaches:
the traditional procedural approach with a great switch (easy to add new functions, hard to add new classes)
the visitor pattern (quite similar: easy to add new visitors, hard to add new classes)
a simple interface approach (easy to add new classes, hard to add new functions)
I'm looking for a way to be able to add both new functions and new classes without having to modify the functions or existing classes.
This should not fail upon requesting a certain combination of object / function, at least not after a check I could do once after program startup.
Here are the approaches I used so far:
Traditional procedural approach:
enum WidgetType {A,B,C,}
interface IWidget
{
WidgetType GetWidgetType();
}
class WidgetA
{
public WidgetType GetWidgetType() {return WidgetType.A;}
}
class WidgetB
{
public WidgetType GetWidgetType() {return WidgetType.B;}
}
class WidgetC
{
public WidgetType GetWidgetType() {return WidgetType.C;}
}
// new classes have to reuse existing "WidgetType"s
class WidgetC2
{
public WidgetType GetWidgetType() {return WidgetType.C;}
}
class Functions
{
void func1(IWidget widget)
{
switch (widget.GetWidgetType())
{
case WidgetType.A:
...
break;
case WidgetType.A:
...
break;
case WidgetType.A:
...
break;
default:
// hard to add new WidgetTypes (each function has to be augmented)
throw new NotImplementedException();
}
}
// other functions may be added easily
}
Traditional object-oriented approach (Visitor-Pattern):
interface IWidgetVisitor
{
void visit(WidgetA widget);
void visit(WidgetB widget);
void visit(WidgetC widget);
// new widgets can be easily added here
// but all visitors have to be adjusted
}
interface IVisitedWidget
{
void accept(IWidgetVisitor widgetVisitor);
}
class WidgetA : IVisitedWidget
{
public void accept(IWidgetVisitor widgetVisitor){widgetVisitor.visit(this);}
public void doStuffWithWidgetA(){}
}
class WidgetB : IVisitedWidget
{
public void accept(IWidgetVisitor widgetVisitor){widgetVisitor.visit(this);}
public void doStuffWithWidgetB(){}
}
class WidgetC : IVisitedWidget
{
public void accept(IWidgetVisitor widgetVisitor){widgetVisitor.visit(this);}
public void doStuffWithWidgetB(){}
}
class SampleWidgetVisitor : IWidgetVisitor
{
public void visit(WidgetA widget){ widget.doStuffWithWidgetA(); }
public void visit(WidgetB widget){ widget.doStuffWithWidgetB(); }
public void visit(WidgetC widget){ widget.doStuffWithWidgetC(); }
}
simple interface approach:
IWidget
{
void DoThis();
void DoThat();
// if we want to add
// void DoOtherStuff();
// we have to change each class
}
WidgetA : IWidget
{
public void DoThis(){ doThisForWidgetA();}
public void DoThat(){ doThatForWidgetA();}
}
WidgetB : IWidget
{
public void DoThis(){ doThisForWidgetB();}
public void DoThat(){ doThatForWidgetB();}
}
WidgetC : IWidget
{
public void DoThis(){ doThisForWidgetC();}
public void DoThat(){ doThatForWidgetC();}
}
It really comes down to where you see the code being most volatile. I suppose I would go the route of having a base class that the Widgets derive from with each function marked virtual so adding a new function doesn't require that all deriving classes provide an implementation and your code won't fail if you call the function on a concrete class that hasn't provided a Widget specific implementation.
I'm facing a similar problem - essentially the issue here is that of multiple dispatch, which is not well-supported in single-dispatch OO languages.
The compromise I have come to is an extensible variation on your Procedural example.
It uses a Mediator (or Coordinator) with a dictionary to register and resolve the actions that should occur between two objects. In the following code example, I am using the problem of collisions between two objects.
The basic structures are:
enum CollisionGroup { Bullet, Tree, Player }
interface ICollider
{
CollisionGroup Group { get; }
}
The Mediator object is defined as follows:
class CollisionResolver
{
Dictionary<Tuple<CollisionGroup, CollisionGroup>, Action<ICollider, ICollider>> lookup
= new Dictionary<Tuple<CollisionGroup, CollisionGroup>, Action<ICollider, ICollider>>();
public void Register(CollisionGroup a, CollisionGroup b, Action<ICollider, ICollider> action)
{
lookup[Tuple.Create(a, b)] = action;
}
public void Resolve(ICollider a, ICollider b)
{
Action<ICollider, ICollider> action;
if (!lookup.TryGetValue(Tuple.Create(a.Group, b.Group), out action))
action = (c1, c2) => Console.WriteLine("Nothing happened..!");
action(a, b);
}
}
Yuck! It doesn't look that nice but that is mainly due to the generic types and lack of supporting objects. I haven't made any for this example because that would introduce too much complexity for the scope of this answer.
The object is used like so:
var mediator = new CollisionResolver();
mediator.Register(CollisionGroup.Bullet, CollisionGroup.Player,
(b, p) => Console.WriteLine("A bullet hit {0} and it did not end well", p));
mediator.Register(CollisionGroup.Player, CollisionGroup.Tree,
(p, t) => Console.WriteLine("{0} ran into a tree. Ouch", p));
mediator.Register(CollisionGroup.Player, CollisionGroup.Player,
(p1, p2) => Console.WriteLine("{0} and {1} hi-fived! Yeah! Awesome!", p1, p2));
var jeffrey = new Player("Jeffrey");
var cuthbert = new Player("Cuthbert");
var bullet = new Bullet();
var tree = new Tree();
mediator.Resolve(jeffrey, cuthbert); // Jeffrey and Cuthbert hi-fived! Yeah! Awesome!
mediator.Resolve(jeffrey, tree); // Jeffrey ran into a tree. Ouch
mediator.Resolve(bullet, cuthbert); // A bullet hit Cuthbert and it did not end well
mediator.Resolve(bullet, tree); // Nothing happened..!
This approach is the most extensible I can find. To add a new reaction or a new type, all that is needed is a new enum member and a call to the .Register() method.
Points for expansion on the above approach:
A generic DispatchMediator<TType, TEnum> is trivially implemented
Similarly, the Tuple<T, T> and Action<T, T> types can be condensed to accept a single type parameter
You could even go further and change the ICollider interface to a generic one if you want to reuse the pattern in several places
The use of extensible enums solves another issue of extensibility (adding a new type)

How to check the type of a list if inheritance is used

I'm currently working on a C# program that creates a List, of object Task, the object Task is a base class and many other inherit from it. What I want to is compare the type of one of the object within said list to see which form should be opened in order to edit it.
This is the code I have already created.
private void itemEdit_Click(object sender, EventArgs e)
{
int edi = taskNameBox.SelectedIndex;
Task checkTask = todoList.ElementAt(edi);
if(checkTask.GetType is Note)
{
noteBuilder editNote = new noteBuilder(todoList);
editNote.Show();
}
else if(checkTask.GetType is extendedTask)
{
extendedTaskBuilder editTask = new extendedTaskBuilder(todoList);
editTask.Show();
}
else if(checkTask.GetType is Reminder)
{
reminderBuilder editReminder = new reminderBuilder(todoList);
editReminder.Show();
}
else if (checkTask.GetType is Appointment)
{
appointmentBuilder editAppointment = new appointmentBuilder(todoList);
editAppointment.Show();
}
}
On a secondary note would it be easier if instead of passing the list between the forms and generating a new object of the form that display information that I instead pass a single object between forms and just update the form every time a new element is added to the list.
Many thanks
Have you tried checking like this:
if (checkTask is Note)
{
}
...
Have you considered creating a base class for all types you are now switching between and call a virtual (abstract) method?
Put all code now in the if in the overridden abstract method.
Advantages:
- The intelligence of the switch is within the classes where it belongs.
- When a new type is added you get a compiler error to also add this feature to the new type.
I suggest that instead of doing that series of ‘if’ clauses, you use inheritance to achieve what ou need. First you create a virtual method in your base class. A virtual method means it won't have any implementation in the base class, only the declaration:
public class Task
{
(...)
public virtual void ShowEditForm(IList todoList);
(...)
}
Then you create the child class methods (I'm assuming the todoList object is a IList, but just change it if it is not).
public class Note: Task
{
(...)
public override void ShowEditForm(IList todoList)
{
(new noteBuilder(taskToEdit)).Show();
}
(...)
}
public class Reminder: Task
{
(...)
public override void ShowEditForm(IList todoList)
{
(new reminderBuilder(taskToEdit)).Show();
}
(...)
}
I didn't write all the classes, but I think you've got the idea. To call the method, you just call the method from Task class, and the right method will be executed:
int edi = taskNameBox.SelectedIndex;
Task checkTask = todoList.ElementAt(edi);
checkTask.ShowEditForm(todoList);
This way, when you want to create new types of Task, you just have to create the child class, with the proper method, and the inheritance system will do the rest.
One more thing, the override keyword in the child method declaration is important, because it says to the compiler that this method should be called even if you call it from the BaseClass.
First, to your second note. What you are talking about doing is having a global object that all forms refer to in some parent. That can work, however you will need to make sure there is some mechanism in place that makes sure all of the forms are synchronized when one changes, and this can get messy and a bit of a mess to maintain. I am not necessarily advocating against it per say, but just adding words of caution when considering it :)
As to your posted code, it would probably be better to turn this into a Strategy Pattern approach, where all forms inherit from a base class/interface which has a Show method. Then all you need to do is call checkTask.Show(todoList);. If you do not want that coming from the Task, then you could have your forms all inherit from the above base and you could use a factory pattern that takes in the Task and list and returns the appropriate form on which you simply call form.Show();
Code like this is difficult to maintain, you are probably better off abstracting this out, like so (assuming Task is not the one included in .net):
public interface IBuilder
{
void Show();
}
public abstract class Task
{
// ...
public abstract IBuilder GetBuilder(TaskList todoList);
// ...
}
public class Note : Task
{
public override IBuilder GetBuilder(TaskList todoList)
{
return new noteBuilder(todoList);
}
// ...
}
// etc.
private void itemEdit_Click(object sender, EventArgs e)
{
int edi = taskNameBox.SelectedIndex;
Task checkTask = todoList.ElementAt(edi);
IBuilder builder = checkTask.GetBuilder(todoList);
builder.Show();
}
Alternately, you can use an injection pattern:
public abstract class Task
{
protected Task(Func<TaskList, IBuilder> builderStrategy)
{
_builderStrategy = builderStrategy;
}
public IBuilder GetBuilder(TaskList todoList))
{
return _builderStrategy(todolist);
}
}
public class Note : Task
{
public Note(Func<TaskList, IBuilder> builderStrategy) : base(builderStrategy) {}
}
// ...
note = new Note(x => return new noteBuilder(x));

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