C# Easily removable class, MonoGame framework, Visual Studio 2013 - c#

I am developing a 2D game in MonoGame with Visual Studio 2013. Due to the ease of implementation, I also choose to implement the editor as a static class that contains ALL the editor functionality (key/mouse events, draw calls, other logic). I used Windows Forms as it was quite easy to do and I do not care much for performance for this task.
The way it works is that the Editor instances a form with the editor controls and that allows me to perform operations directly to the game data in memory for each draw layer, such as adding/moving/removing tiles or other elements. I found it quite convenient and it works fine so far with only a minimal amount of code brought to the main game/rendering loop. At the same time, I am able to view and work on the game window directly.
To exclude the editor at any point, all I need to do is to delete the folder from the project that contains the Editor class along with any referenced classes and comment-out a few lines of code, giving me the clean version of the game.
However, I recently discovered I need to add more logic to the draw loop, the first issue being I need to visually indicate the selected tiles with a rectangle border around. This would be easy to do if I would interfere with the main game draw logic (the Renderer class), but I certainly do not want to keep the code there because it may get complex.
I could come over the drawn result (see below code, at the Draw override) and paint over, but that would force me to re-use a part of the rendering code in the editor. Also, that would loop again over all tiles and logic and I find that inefficient.
The best way I thought about implementing this is to call Editor.DrawLayer() from the game's DrawLayer() 's own method if it exists. If it does not exist, do nothing. This way I would not need to remove anything else from the code, just delete the Editor class.
namespace Main
{
public class Main : Game
{
...
public Main()
{
...
}
protected override void Initialize()
{
...
Editor.Initialize(); // TODO remove these on publish
}
protected override void LoadContent()
{
...
Editor.LoadContent(); // TODO remove these on publish
}
protected override void UnloadContent()
{
...
Editor.Unload(); // TODO remove these on publish
}
protected override void Update(GameTime gameTime)
{
Editor.Update(); // TODO remove these on publish
...
Renderer.Instance.Update(gameTime);
...
}
protected override void Draw(GameTime gameTime)
{
Renderer.Instance.Draw(spriteBatch, gameTime);
...
// Editor.Draw(); // I would avoid this
}
}
}
I am able to recognize if the Editor class exists by using this method:
private static void GetAssemblies()
{
Assembly projectAssemblies = Assembly.GetExecutingAssembly();
namespaceList = new List<string>();
foreach (Type type in projectAssemblies.GetTypes())
{
namespaceList.Add(type.FullName);
}
}
public void TryStartingEditor()
{
if (namespaceList.IndexOf("Main.Editor") > -1)
{
Config.EditorExists = true;
}
}
However, I cannot add any code that would survive the Editor class removal as any namespace such as:
Editor.whatever();
would not be legal any more.
My main question is: What would be a good way of calling this class's methods that may not exist at a later point in time without the compiler going crazy?
I am open for any OTHER suggestion that would allow me to implement the editor as less-intrusive as possible relative to the main game loop.
Note. I know that removing a class is a simple matter of also deleting all pieces of code that reference it and that's not a big deal, maybe 5 minutes when the project is done, so know I am not determined to use this method, I am curious if it can be done with ease.
Later edit. I believe I can summarize the problem simply by showing these two scenarios. I would like scenario 2 to be possible somehow.
Scenario 1. Editor class exists
public static class Editor {
... everything about editor
}
public function AnyFunctionAnywhere() {
...
if (EditorExists) {
// Ok, we run this, class exists, no problem.
Editor.callSomeMethod();
}
....
}
Scenario 2. Editor class is suddenly missing and we don't necessarily want to remove all calls to it.
public function AnyFunctionAnywhere() {
...
if (EditorExists) {
// Somehow don't throw "The name 'Editor' does not exist in the current context".
Editor.callSomeMethod();
}
...
}
Thank you kindly and let me know if I should explain more clearly any aspects.

I believe I found a good solution using System.Reflection. I created a new singleton class that handles calling in the manner I wanted and it seems to work fine. Here it is below.
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Main
{
public class LocalSystem
{
// Use this to store the list of classes/methods. bool is redundant
public static Dictionary<Tuple<string, string>, bool> classMethods = new Dictionary<Tuple<string, string>, bool>();
// Singleton
private static LocalSystem instance;
public static LocalSystem Instance
{
get
{
if (instance == null)
{
GetAssemblies(); // We do this once. I suspect this to be slow.
instance = new LocalSystem();
}
return instance;
}
}
// Editor specific callers
public void InvokeEditorMethod(string methodName) // Call function
{
invokeClassMethod("Main.Editor", methodName, null);
}
public void InvokeEditorMethod(string methodName, params object[] values) // Call function with some arguments
{
invokeClassMethod("Main.Editor", methodName, values);
}
// This tries to invoke the class.method
private void invokeClassMethod(string className, string methodName, params object[] values)
{
if (!ClassHasMethod(className, methodName)) // We check if the class name and method exist. If not, we bail out.
return;
try
{
Type.GetType(className).GetMethod(methodName).Invoke(null, values);
}
catch(Exception e)
{
if (e is TargetParameterCountException) // This error might be more common than others
{
throw new Exception("Wrong number of parameters provided for method " + methodName + " within " + className);
}
throw; // Something else went wrong
}
}
private static void GetAssemblies()
{
Assembly asm = Assembly.GetExecutingAssembly();
foreach (Type type in asm.GetTypes())
{
string discoveredClass = type.FullName;
foreach (MethodInfo method in Type.GetType(discoveredClass).GetMethods())
{
if (!classMethods.ContainsKey(new Tuple<string, string>(discoveredClass, method.Name)))
classMethods.Add(new Tuple<string, string>(discoveredClass, method.Name), true);
}
}
}
private static bool ClassHasMethod(string className, string methodName)
{
return classMethods.ContainsKey(new Tuple<string, string>(className, methodName));
}
}
}
Usage:
LocalSystem.Instance.InvokeEditorMethod("Initialize");
or
LocalSystem.Instance.InvokeEditorMethod("MethodWithParams", 1, "foo");
Notes.
I haven't covered returning values from invoking functions. Tried for a few minutes but it seems a bit more complicated than I am willing to invest time for. Considering my working model, I should never expect a return value. If I would, it would mean I am moving the editor logic to where it isn't supposed to be, therefore I abandoned this aspect.
You will notice that the exposed methods use the "Main.Editor" class. This is particular for my needs, but if you need to handle multiple arbitrary classes, you can expose a more broad implementation of invokeClassMethod.
Thanks!

Related

c# call a method whenever another method ends?

Although this question might sound stupid at first glance, please hear me out.
c#'s get{} and set{} methods are increadibly usefull in situations when you do not know how you porgramming goals will evolve while you build your code. I enjoyed their freedom many a time and now I wonder if there is something similar for methods but in a bit different light.
As I am working in gamedev, it is a very common practice to extend/update/improve existing code day-in day-out. Therefore, one of the patterns I taught myself to follow is to never use "return" statement more than once in the most of my methods.
The reason why I do this is to always be able to write something at the bottom of the method and be sure that the line I have written is always called 100% of the time once my method ENDS.
Here is an example:
public void Update()
{
UpdateMovement();
if (IsIncapacitated)
return;
if (IsInventoryOpened)
{
UpdateInventory();
return;
}
if (Input.HasAction(Actions.Fire))
{
Fire();
return;
}
else if (Input.HasAction(Actions.Move))
{
Move(Input.Axis);
return;
}
}
Now imagine that this method is called dozens of times in many places across the entirety of your project. And then the next day you decide that you need to call UpdatePhysics() method at the very end of your Update() method. In this case there are only 4 returns, it could be much worse in reality.
Then imagine that such decesions happen several times a day every day. Bad planning you may say? I might agree with you, but I do think that freedom of development is essential in modern coding. I don't think you should kill yourself trying to anticipate every turn your project might take before you start writing code.
One way to insure that problems like the one I described above never happen is to rewrite the method as follows:
public void Update()
{
UpdateMovement();
if (!IsIncapacitated)
{
if (IsInventoryOpened)
{
UpdateInventory();
}
else
{
if (Input.HasAction(Actions.Fire))
{
Fire();
}
else if (Input.HasAction(Actions.Move))
{
Move(Input.Axis);
}
}
}
}
In this case you can always add a line at the bottom and be sure it will always get called nomatter what.
So I wanted to ask if there is another approach that could allow for placing "return"-s wherever you wish while still being able to add extra code easily at the bottom of the method any time. Maybe there is any form of syntax in c# that does it for you? Or maybe there is a better coding practice that eliminates such problem?
UPDATE: As I started receiving answers, I realized that I need to clarify things a bit.
'try/catch/finally' is an overkill - I will never use them. They have severe performance penalty on catch(), they screw up 'Edit and continue' feature in Visual Studio and they just look ugly.
Idealy I need to be able to access local variables in the Update() method from any code I decide to add at the end of the method,
When I wrote the question, I already had an answer - nesting. My second code sample has no returns and, therefore I can add code to the very bottom of the method and it will work 100% of the time, while I will be able to use local variables. Nesting is bad though, and that is why I am here searching for a BETTER solution.
UPDATE 2: I was actually mistaken about try/catch because I did not know that you can skip catch alongside it's performance penalties and only have finally. However, this solution is still worse than the nesting solution provided in the question, because in your newly added finally block you no longer can use return statements. So basically you can do whatever you want when you write the method the first time, but once you extend it - you are back to nesting.
One simple suggestion is to wrap your function. For example:
public void UpdateCall()
{
Update();
AfterUpdate code goes here.
}
Using a try/finally block should work;
public void Update()
{
try
{
UpdateMovement();
if (IsIncapacitated)
return;
if (IsInventoryOpened)
{
UpdateInventory();
return;
}
if (Input.HasAction(Actions.Fire))
{
Fire();
return;
}
else if (Input.HasAction(Actions.Move))
{
Move(Input.Axis);
return;
}
}
finally
{
//this will run, no matter what the return value
}
}
The performance costs of using try/finally (not try/catch!) are minimal
You cannot use return in the finally block;
If you were able to return a different value from the Finally block,
this value would always be returned, whatever the outcome of the
instructions above. It just wouldn't make sense..
I suggest wrapping the code into try..finally block:
public void Update() {
try {
...
// you can return
if (someCondition)
return;
...
// throw exceptions
if (someOtherCondition)
throw...
...
}
finally {
// However, finally will be called rain or shine
}
}
You can use try-catch-finally (C#-Reference) without a catch block.
try
{
//your business logic here
}
finally
{
//will be called anytime if you leave the try block
// i.e. if you use a return or a throw statement in the try block
}
With the modern c# 8 syntax you may introduce some disposable 'ScopeFinalizer' object or name whatever you want:
public class ScopeFinalizer : IDisposable
{
private Action delayedFinalization;
public ScopeFinalizer(Action delayedFinalization)
{
this.delayedFinalization = delayedFinalization ?? throw new ArgumentNullException(nameof(delayedFinalization));
}
public void Dispose()
{
delayedFinalization();
}
}
//usage example
public async Task<bool> DoWorkAsyncShowingProgress()
{
ShowActivityIndicator();
using var _ = new ScopeFinalizer(() =>
{
// --> Do work you need at enclosure scope leaving <--
HideActivityIndicator();
});
var result = await DoWorkAsync();
HandleResult(result);
//etc ...
return true;
}
Useful link:
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#using-declarations
Don't use the returns as it makes your code smelly.
public void Update()
{
UpdateMovement();
if (IsIncapacitated){
return;
}
if (IsInventoryOpened)
{
UpdateInventory();
}
else if (Input.HasAction(Actions.Fire))
{
Fire();
}
else if (Input.HasAction(Actions.Move))
{
Move(Input.Axis);
}
}
Also, your second solution has too much nesting, also confusing and smelly.
A problem with the current approach is that it requires changes to the Update() method whenever we want to add a new action.
Another approach is to remove the hard-coding of the update actions and configure the class with a set of update actions.
From the code given here we have
Actions that always happen (e.g. UpdateMovement)
Actions that happen if a test is passed (e.g. UpdateInventory)
Actions that cause a return if they are executed (e.g. Fire())
We can encapsulate these in an interface
public interface IUpdateAction
{
bool ShouldUpdate();
// return true if we want this to be the last action to be executed
bool Update();
}
and wrap various actions and decisions in the class using
public class DelegateUpdateAction : IUpdateAction
{
private Func<bool> _updateAction;
private Func<bool> _shouldUpdateCheck;
public DelegateUpdateAction(Action action, bool isLastAction = false, Func<bool> shouldUpdateCheck = null)
: this(() =>
{
action();
return isLastAction;
},
shouldUpdateCheck)
{ }
public DelegateUpdateAction(Func<bool> updateAction, Func<bool> shouldUpdateCheck = null)
{
if(updateAction == null)
{
throw new ArgumentNullException("updateAction");
}
_updateAction = updateAction;
_shouldUpdateCheck = shouldUpdateCheck ?? (() => true);
}
public bool ShouldUpdate()
{
return _shouldUpdateCheck();
}
public bool Update()
{
return _updateAction();
}
}
To replicate the example we could use
public class Actor
{
private IEnumerable<IUpdateAction> _updateActions;
public Actor(){
_updateActions = new List<IUpdateAction>{
new DelegateUpdateAction((Action)UpdateMovement),
new DelegateUpdateAction((()=>{ }), true, () => IsIncapacitated),
new DelegateUpdateAction((Action)UpdateInventory, true, () => IsInventoryOpened),
new DelegateUpdateAction((Action)Fire, true, () => Input.HasAction(Actions.Fire)),
new DelegateUpdateAction(() => Move(Input.Axis), true, () => Input.HasAction(Actions.Move))
};
}
private Input Input { get; set; }
public void Update()
{
foreach(var action in _updateActions)
{
if (action.ShouldUpdate())
{
if (action.Update())
break;
}
}
}
#region Actions
private bool IsIncapacitated { get; set; }
private bool IsInventoryOpened { get; set; }
private void UpdateMovement()
{
}
private void UpdateInventory()
{
}
private void Fire()
{
}
private void Move(string axis)
{
}
#endregion
}
The actions are executed in the order in which they are registered, so this gives us the ability to inject a new action into the execution sequence at any point.
UpdateMovement() always happens and doesn't return
IsIncapacitated() is a test with a null action. It returns if executed so we get our 'do-nothing-else-if-incapacitated' behaviour
UpdatedInventory() occurs if the inventory is open and then returns
Each of the HasAction checks return if executed.
Note If I have read the question better before writing the code I would have reversed the defaults as most actions seem to be 'return if executed'.
If we need to add 'UpdatePhysics()', we add a method to the class and add an entry in the appropriate place in the list of update actions. No changes to the Update method.
If we have derived classes with different actions we can add the facility to add (or remove) actions in the derived classes and either inherit and modify the default actions or replace them with a different set.
After seeing the other solutions I can't think of a truly dynamic solution that has only the functions you want to call in the update loop.
Here are some ideas though I doubt any of them are better than making a good design. Joe C has the correct idea of how you should structure this kind of thing.
You could make a container of actions that need to be performed each update loop. Remove and add specific actions depending on the changes to circumstances. Such as a IsNowIncapacitated event that remove the Handling action from the list. Though I have little experience with actions, I believe you can set up delegates that the actions point to. Not sure what the cost to performance is.
A temporary thing you could do so you can keep adding logic is have your return statements return a void function with some constant logic you want performed, though all it really will do is separate your update code between two methods. It is not very neat or as efficient as structuring your code appropriately like in Joe C's example.
public void PostUpdate()
{
//stuff that always happens
PhysicsUpdate();
}
public void Update()
{
UpdateMovement();
if (IsIncapacitated)
return PostUpdate();
if (IsInventoryOpened)
{
UpdateInventory();
return PostUpdate();
}
}

Dispose static variable on page reload or use something else

I don't usually code C#, when i do, i suck
I have parent Class and two derived class. both derived class share an expensive calculation which slightly differ for second one. I am trying to avoid calculate one.
However, i want
interface ICalculator
{
double getValue(int id);
void setContext(int c);
}
abstract class CalculatorBase: ICalculator
{
internal static Dictionary<int, double> output = null;
internal void loadData()
{
//load data
}
internal computeAll()
{
//do expenseive calculation and set output
output = something
}
double abstract getValue(int id);
void abstract setContext(int c);
}
class ChildCalculator1 : CalculatorBase
{
override void setContext(int c)
{
if (output !=null)
return;
loadData();
computeAll();
}
public ovverride getValue(int id)
{
return output[id];
}
}
class ChildCalculator2 : CalculatorBase
{
override void setContext(int c)
{
if (output !=null)
return;
loadData();
computeAll();
}
public ovverride getValue(int id)
{
return output[id] -1;
}
}
requirements:
if ChildCalculator1 or ChildCalculator or both (one after another) is called, computeAll will be computed once.
However, if you reload this page i want to calculate once. This means i want to calculate once every pageload
Question: How can i access parent properties (output) from two different child instance (ChildCalculator1, ChildCalculator) and if you reload the page, that proproperty (output) will be recalculated? Currently I made output as static but this doesnt change when i reload the page.
Static variable might not be the right thing as they survive through out the application not page load. How can i dispose after pageload is done or anything else you can suggest?
Your code isn't so bad... but it could definitely be better. :)
You are correct that the static dictionary will not get garbage collected. (In C# the Garbage Collector free's unused memory) You need all instances of calculator to share your dictionary and you want to dispose of it when you are done. You could implement a little factory that builds the calculators and gives them all a single instance of the dictionary. A very simple way to do this however is just to manually manage the static dictionary.
If you add the following method in CalculatorBase
public static void DoneWithCalculations()
{
// By removing your static reference to your dictionary you
// allow the GC to free the memory.
output = null;
}
You can then call this static method when you are all done with your calculators (for instance at the end of PageLoad) like so...
CalculatorBase.DoneWithCalculations();
This will do what you need and doesn't force you to work in C# more than you have to. :)

Is it possible to access caller object from stack trace and set its property

Hi I have a possible design flaw and i need to solve it with an extension method.
Lets say I have a class and it has a property of StringCollection. Example code
public class MyProblematicClass
{
public IDbAccess Db{get;set;}
public StringCollection Errors{get;set;}
public MyProblematicClass(IDbAcces db){ Db=db;}
public int SetItem(Item i)
{
var id = Db.Save(i);
this.Errors = Db.Erros;
return id;
}
}
What I am doing is, in my unit test class I mock IDbAccess. This class validates object according to attributes. If any error occures it doesnt hit to db, it just fills its own Errors collection. For unit test I use another dbclass which just runs validation routines and here is problem i cannot get Error. Let me give you example for further understanding ( I know design is problematic, but for now I want to deal with it without changing anything)
public static class MyDbExtension
{
public static Save(Item i)
{
Validation v = new Validation();
var erros = v.ValidateObject(i);
//Here is problem i cannot pass it to MyProblematicClass
if ( errors.Count > 0 )
return -1;
else
return 1;
/* what I want to is :
var stackTrace = new StackTrace(); get stack trace
var object = stackTrace.GetFrame(1).GetMethod().GetObject() or sth like that. get object
object.GetProperties()[0].SetValue(object,errors,null); find property and set it.
*/
}
}
in my unit test :
public class UnitTest
{
Mock<IDbAccess> _db ;
MyProblematicClass _mpc;
pubic Setup()
{
_db.Setup(x=>x.Save(It.IsAny<Item>).Returns(u =>MyDbExtension.Save(u));
_mpc = new MyProblematicClass(_db.Object);
}
public void SetItem_EmptyObject_Contains3Erros()
{
Item i = new Item();
_mpc.SetItem(i);
//At this point i cannot set _mpc.Errors
}
What I want to achieve is in my DbExtension class can I access caller class and set its Errors property? I tried but it wasn unlikely yet. If anyone has any decent solution I will be appreciative and of course you can comment on design problems.
Edit
I appreciate Alex's answer he just said ignore Save method just mock Erros property and it will be ok. That make sense but what I wonder is in question, is it possible to access Stack Trace and manipulate caller methods object's property?
Thanks in advance.
You need to setup the return value of _db.Errors, something like this:
public class UnitTest
{
Mock<IDbAccess> _db ;
MyProblematicClass _mpc;
StringCollection errors;
pubic Setup()
{
_db.Setup(x=>x.Save(It.IsAny<Item>).Returns(u =>MyDbExtension.Save(u));
_db.Setup(x=>x.Errors).Returns(errors);
_mpc = new MyProblematicClass(_db.Object);
}
public void SetItem_EmptyObject_ContainsError()
{
errors.Add("Expected Error!");
Item i = new Item();
_mpc.SetItem(i);
Assert.AreEqual("Expected Error!", _mpc.Errors[0]);
}
}
I must admit I don't really follow your design, why are you using a static method for save? You could just as easily have the line:
_db.Setup(x=>x.Save(It.IsAny<Item>).Returns(-1);
Then test IDbAccess.Save() independently.
In your 'extension' class the save method has no return value, and MyProblematicClass does not inspect the return value before assigning errors.
Not sure to fully understand the question, but you cannot access the parameters on the stack from a normal program. Runtime metadata is only about static information (method, properties, constants, etc...).
I believe only a debugger (which is considered as a special beast of its own) can do this without changing the program/source, and this has serious performance cost. As a side note, here is a link that explain how to build your own managed debugger (.NET 4): CLR Managed Debugger (mdbg) Sample 4.0
Another solution is to instrument your code (automatically or using a tool) to add some tracing call that can capture the list of parameters on each traced methods. Tools like PostSharp can do this. Here is another link: Non-Invasive Tracing & Logging
You could use unmanaged debugging API to access the call stack and get the object previous function on the stack was called on.
The problem is, the stack may not contain the method you are expecting. In cases such as inlining and tail call optimization, the call stack doesn't contain the previous method called, which means you can't reliably do what you want.
For more information see this answer by Eric Lippert.
This doesn't use the call stack, but might get you some mileage:
class CalledClass
{
public static void PokeCaller()
{
Program._this.Error = "Error!!!";
}
}
class Program
{
public string Error = null;
[ThreadStatic] public static Program _this;
public void Run()
{
_this = this;
CalledClass.PokeCaller();
Console.WriteLine(Error);
Console.ReadKey();
}
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
}
Making Errors be [ThreadStatic] might be a more direct way to do it... or some other variation on that theme. You might also combine it with stack trace checking to see if you were actually called by something that has "Errors" attribute before setting it...

Making compiler to complain if static call order of user defined functions voilates some rules

Consider this code.
public class Class1
{
public void ThisShouldNotCompileBecauseOrderWasVoilated()
{
Call2();
Call1();
}
public void ThisShouldCompileBecauseProperOrderIsPresent()
{
Call1();
Call2();
}
private void Call1()
{
// some code
}
private void Call2()
{
// some more code
}
}
What code (or attribute) should I add in Call1()/Call2() which ensures that compiler complains for 1st method and passes for 2nd method. There will be some rule list which compiler will have to refer if order is not correct. In this example the rule list can say "Call1 Call2", meaning call Call1() before Call2()
This is for C# language for .NET 4.0
Thanks!
There's nothing within normal C# that you can specify for this.
You may be able to use something like NDepend to detect this, but I'm not sure.
You can create your own attribute and mark your methods using it. Then create an FXCop rule. FXCop fully integrates with your build process, and as long as both calls are taking place within the same method, the rule should be fairly easy to flesh out.
the compiler can't enforce method call ordering, since in many cases it cannot determine statically what the call order is. For example:
public void whichOrder(boolean b)
{
if (b) call1();
if (!b) call2();
if (b) call2();
if (!b) call1();
}
If it's necessary that the methods are called in the correct order, you have a few choices:
document the call order, so that callers know what to do. This doesn't enforce the order, but at least makes coders aware of it.
add state to your object to remember which method was called last, and validate the current called method is allowed next. This enforces the method check at runtime.
Use a mock framework (e.g. Moq) to unit test your clients. This checks at build time that the order is correct.
Which approach you choose depends on how critical the correct ordering is, and the consequences of calling the methods in the wrong order.
An alternative is to rework your design so that method ordering doesn't become an issue. For example, wrap both methods up in a third, call3() that invokes call1() and call2() in the correct order. Or perhaps, have call2() invoke call1() if it has not already been executed, and have call1() check if it's already run, and return silently if it doesn't need to run. If clients invoke call2() then call1(), you still internally get the effect of call1() first (from call2()'s internal call to call1()) and the client's call to call1() results in a no op.
E.g.
public void call3()
{
call1();
call2();
}
or
public void call2()
{
call1();
// rest of call2's logic
}
private boolean call1Called = false;
pubic void call1()
{
if (!call1Called)
{
call1Called=true;
call1Impl();
}
}
This is not exactly what you are asking ... but you could introduce another class:
public class Another1
{
public Another2 Call1()
{
// some code
return new Another2();
// could pass 'this' to Another2 constructor so it has all state
}
}
public class Another2
{
public void Call2()
{
// some more code
}
}
Now, starting from an instance of Another1 you can only do obj.Call1().Call2() and never obj.Call2().Call1(). Better yet, this enforcement is in the IDE as you type. Take a look at 'fluent' patterns also.

Initializing constructor from stored cache in C#

I'm not sure exactly how to describe this question, but here goes. I've got a class hierarchy of objects that are mapped in a SQLite database. I've already got all the non-trivial code written that communicates between the .NET objects and the database.
I've got a base interface as follows:
public interface IBackendObject
{
void Read(int id);
void Refresh();
void Save();
void Delete();
}
This is the basic CRUD operations on any object. I've then implemented a base class that encapsulates much of the functionality.
public abstract class ABackendObject : IBackendObject
{
protected ABackendObject() { } // constructor used to instantiate new objects
protected ABackendObject(int id) { Read(id); } // constructor used to load object
public void Read(int id) { ... } // implemented here is the DB code
}
Now, finally, I have my concrete child objects, each of which have their own tables in the database:
public class ChildObject : ABackendObject
{
public ChildObject() : base() { }
public ChildObject(int id) : base(id) { }
}
This works fine for all my purposes so far. The child has several callback methods that are used by the base class to instantiate the data properly.
I now want to make this slightly efficient. For example, in the following code:
public void SomeFunction1()
{
ChildObject obj = new ChildObject(1);
obj.Property1 = "blah!";
obj.Save();
}
public void SomeFunction2()
{
ChildObject obj = new ChildObject(1);
obj.Property2 = "blah!";
obj.Save();
}
In this case, I'll be constructing two completely new memory instantiations and depending on the order of SomeFunction1 and SomeFunction2 being called, either Property1 or Property2 may not be saved. What I want to achieve is a way for both these instantiations to somehow point to the same memory location--I don't think that will be possible if I'm using the "new" keyword, so I was looking for hints as to how to proceed.
Ideally, I'd want to store a cache of all loaded objects in my ABackendObject class and return memory references to the already loaded objects when requested, or load the object from memory if it doesn't already exist and add it to the cache. I've got a lot of code that is already using this framework, so I'm of course going to have to change a lot of stuff to get this working, but I just wanted some tips as to how to proceed.
Thanks!
If you want to store a "cache" of loaded objects, you could easily just have each type maintain a Dictionary<int, IBackendObject> which holds loaded objects, keyed by their ID.
Instead of using a constructor, build a factory method that checks the cache:
public abstract class ABackendObject<T> where T : class
{
public T LoadFromDB(int id) {
T obj = this.CheckCache(id);
if (obj == null)
{
obj = this.Read(id); // Load the object
this.SaveToCache(id, obj);
}
return obj;
}
}
If you make your base class generic, and Read virtual, you should be able to provide most of this functionality without much code duplication.
What you want is an object factory. Make the ChildObject constructor private, then write a static method ChildObject.Create(int index) which returns a ChildObject, but which internally ensures that different calls with the same index return the same object. For simple cases, a simple static hash of index => object will be sufficient.
If you're using .NET Framework 4, you may want to have a look at the System.Runtime.Caching namespace, which gives you a pretty powerful cache architecture.
http://msdn.microsoft.com/en-us/library/system.runtime.caching.aspx
Sounds perfect for a reference count like this...
#region Begin/End Update
int refcount = 0;
ChildObject record;
protected ChildObject ActiveRecord
{
get
{
return record;
}
set
{
record = value;
}
}
public void BeginUpdate()
{
if (count == 0)
{
ActiveRecord = new ChildObject(1);
}
Interlocked.Increment(ref refcount);
}
public void EndUpdate()
{
int count = Interlocked.Decrement(ref refcount);
if (count == 0)
{
ActiveRecord.Save();
}
}
#endregion
#region operations
public void SomeFunction1()
{
BeginUpdate();
try
{
ActiveRecord.Property1 = "blah!";
}
finally
{
EndUpdate();
}
}
public void SomeFunction2()
{
BeginUpdate();
try
{
ActiveRecord.Property2 = "blah!";
}
finally
{
EndUpdate();
}
}
public void SomeFunction2()
{
BeginUpdate();
try
{
SomeFunction1();
SomeFunction2();
}
finally
{
EndUpdate();
}
}
#endregion
I think your on the right track more or less. You can either create a factory which creates your child objects (and can track "live" instances), or you can keep track of instances which have been saved, so that when you call your Save method it recognizes that your first instance of ChildObject is the same as your second instance of ChildObject and does a deep copy of the data from the second instance over to the first. Both of these are fairly non-trivial from a coding standpoint, and both probably involve overriding the equality methods on your entities. I tend to think that using the first approach would be less likely to cause errors.
One additional option would be to use an existing Obect-Relational mapping package like NHibernate or Entity Framework to do your mapping between objects and your database. I know NHibernate supports Sqlite, and in my experience tends to be the one that requires the least amount of change to your entity structures. Going that route you get the benefit of the ORM layer tracking instances for you (and generating SQL for you), plus you would probably get some more advanced features your current data access code may not have. The downside is that these frameworks tend to have a learning curve associated with them, and depending on which you go with there could be a not insignificant impact on the rest of your code. So it would be worth weighing the benefits against the cost of learning the framework and converting your code to use the API.

Categories

Resources