I’m trying to manage multiple models in a messaging based system. Each model might have values that are dependent on other models. For example:
public class V2Model : BaseModel
{
private int mSomeVal;
private byte mSomeByte;
// …
// Update mSomeByte based on multiple models values
public void SetMultipleDependecyValue(int someIntFromModel1, short someShawteeyFromModel3)
{
mSomeByte = Convert.ToByte((someShawteeyFromModel3 / someIntFromModel1) + mSomeVal);
}
}
I would also like to use the MVC pattern, but instead of passing a Model instance, I thought I would pass in a ‘Repository’ instance. The ‘Repository’ instance would act as a manager for handling all the Model instances. The result would look something like this:
public class V1Controller<ViewType, ModelType>
where ViewType : IV1View
where ModelType : BaseModel
{
ViewType mView;
BaseRepository mBaseRep;
public V1Controller(ViewType view, BaseRepository rep)
{
mView = view;
mBaseRep = rep;
mBaseRep.GetModel<ModelType>().PropertyChanged += new PropertyChangedEventHandler(V1ModelPropertyChanged);
}
void V1ModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "SomeVal":
// Update the view
int some_val = mBaseRep.GetModel<ModelType>().SomeVal;
mView.HexSomeValue = some_val;
// Oh BTW, we know V2Model's value depends on this... update it with V1Model and V3Model's values
short some_short = mBaseRep.GetModel<V3Model>().SomeShawteey;
mBaseRep.GetModel<V2Model>().SetMultipleDependecyValue(some_val, some_short);
break;
}
}
public void UpdateVal(int someValue)
{
mBaseRep.GetModel<ModelType>().SomeVal = someValue;
}
}
In this situation, if V1Model’s property changed, in V1ModelPropertyChanged, I would know the dependency on V2Model’s object, and update it with the appropriate values. Is there a better way of handling this interdependent model scheme, or would this be an acceptable solution? I am not really looking for anything 3rd party.
If you want to handle this elegantly, you're going to need to have some component track the dependencies between the models. When a property changes, you would iterate over all of the dependencies for that property and then update them appropriately.
Perhaps your BaseRepository might hold a reference to a DependencyManager class. That class would have to have a list of all properties which depend on one another.
A simple implementation might look like this:
class PropertyDescriptor
{
public Type ModelType { get; set; }
public string Property { get; set; }
}
class DependencyManager
{
private Dictionary<PropertyDescriptor, List<PropertyDescriptor>> _dependencies = new Dictionary<PropertyDescriptor, List<PropertyDescriptor>>();
public void RegisterDependency(PropertyDescriptor property, PropertyDescriptor dependentProperty)
{
if (!_dependencies.ContainsKey(property))
{
_dependencies.Add(property, new List<PropertyDescriptor>());
}
_dependencies[property].Add(dependentProperty);
}
public IEnumerable<PropertyDescriptor> GetDependentProperties(PropertyDescriptor property)
{
if (!_dependencies.ContainsKey(property))
{
yield break;
}
else
{
foreach (PropertyDescriptor p in _dependencies[property])
{
yield return p;
}
}
}
}
Then when you detect a property change, you can query the DependencyManager for what else needs to change. But be careful to check for circular dependencies when you cascade!
Maybe I'm missing something, but isn't this what the observer pattern is for? If you set up the models as observers of each other (i.e., with delegates or events), then the controller should be able to remain blissfully ignorant of the dependencies.
Related
I'm making a simple game as a practice project based around random events, to make it easier to add new events I’ve decided to use a keyword system where each event gets keywords assigned to them that are then used to process the event, this can be as simple as displaying as message, changing data in the model or rolling again on the random table.
I have a class that randomly decides an event and returns a List of strings with keywords.
I want to make a class where all the keywords are stored as methods that can then be called with the list.
Something like this:
class Keyword
{
public void InputKeywords(List<string> Ikeywords)
{
foreach (var item in Ikeywords)
{
switch (item)
{
case "keyword0":
keyword0();
break;
case "keyword1":
keyword0();
break;
case "keyword2":
keyword0();
break;
}
}
}
private void keyword0()
{
//do something
}
private void keyword1()
{
//do something
}
private void keyword2()
{
//do something
}
}
Now the problem I’m facing is updating the data in the model from the keywords class.
Because the events are chosen at random I don't know for each event what data to send to the class to have it update it.
The solutions I've come up with myself:
Make my model static, no more issues with accessing data, Google tells me this is frowned upon and should be avoided.
Send the model to the Keyword class, do some magic, and return the model. Would be an easy solution but feels wrong to me, from what I've come to understand about MVVM is that the data should be updated from the viewmodel, but I could be thinking too much inside of the box.
Gather all possible data to be changed into a seperate class, send that to the keyword class and update the model afterwards. This sounds like a hassle and feels like I'm just moving the problem elsewhere.
I feel like I'm missing the "right" way of doing this. What would be the "best" approach?
First of all the naming of the keyword class feels misleading here. It is basically an event handler, so I would also name it like on (e.g. RandomEventGenerator)
To your problem I would also not recommend you to use static models. Your testability will suffer from it since you won't use dependency injection there. This being said your second approach seems to go into the right direction. I would suggest to use inject an EventInvoker Interface.
public interface IEventInvoker
{
public void RaiseEvent();
}
This can be implemented in an operator, which has access to your data model and has predefined actions to modify your data.
public class WeatherOperator : IEventInvoker
{
private readonly WeatherEngine _weatherEngine;
public WeatherOperator(WeatherEngine weatherEngine)
{
_weatherEngine = weatherEngine;
}
public void RaiseEvent()
{
StartSunshine();
}
public void StartSunshine()
{
_weatherEngine.RemoveClouds();
_weatherEngine.SetSunPosition(DayTimes.Noon);
}
public void LetItRain()
{
_weatherEngine.SetCloudes(CloudModes.FullCover);
_weatherEngine.SetRain(RainIntesity.Medium);
}
}
With a list of the IEventInvoker you can then go to your EventHandler.
public class RandomEventGenerator
{
private readonly List<IEventInvoker> _eventInvoker;
private readonly Dictionary<string, Action> _eventDictionary;
public RandomEventGenerator(List<IEventInvoker> eventOperator, List<string> keywords)
{
_eventInvoker = eventOperator;
_eventDictionary = RegisterKeywordsToRandomEvents(keywords);
}
private Dictionary<string,Action> RegisterKeywordsToRandomEvents(List<string> keywords)
{
var eventDictionary = new Dictionary<string, Action>();
foreach (var keyword in keywords)
{
var random = new Random();
var index = random.Next(_eventInvoker.Count);
eventDictionary.Add(keyword,_eventInvoker[index].RaiseEvent);
}
return eventDictionary;
}
public void EventByKeyword(string Keyword)
{
_eventDictionary[Keyword].Invoke();
}
public void RandomEvent()
{
var random = new Random();
var index = random.Next(_eventInvoker.Count);
_eventInvoker[index].RaiseEvent();
}
}
Please note that I, to keep it small, didn't used null checks or input validations here, which is highly recommended.
With this approach you have a clear cut bettween your model/data and your viewmodel/data accesor.
When using the MVP pattern for WinForms, I sometimes need to call private methods in my public methods of the presenter and change a few properties of the view. In these situations, how can I efficiently unit test the changes to the view and the behavior of the private methods?
public void OnFileNameChanged(string fileName)
{
_settings = FirstPrivateOperation()
if (_settings == null)
{
_view.A = false;
return;
}
var config = SecondPrivateOperation();
if (config == null)
{
_view.B = true;
return;
}
_view.C = true;
}
Some options, based on what you showed, would be :
mock the two methods which set these values,
break _settings and config or even the two methods which provide the results into a separate class ( like a configuration kind of thing ) and inject the interface of that class as a dependency at whatever level it makes sense. You can then mock those values.
I would pursue one of these options.
In regards to the View values, I would try to separate that. There are number of issues with this code.
you have a OnFileNameChanged metho and you probably can't change its signature and doesn't return anything. So, I would separate the code even more. Take the code out of it and create another method that you control. Do not add any View setting in that one. The purpose ifs to cover the logic and return an object with some calculated values.
Then, in the OnFileNameChanged you assign what you need for the view stuff. In short, take the logic part out and deal with it somewhere else and test that.
You have 3 values that you are assigning to the View object, so make your new method return either one value, or an object with three values, covering each possibility.
public void OnFileNameChanged(string fileName)
{
var calculatedValues = CalculateValues(//might need some params here)
_view.A = calculatedValues.A;
_view.B = calculatedValues.B;
_view.C = calculatedValues.C;
}
public MyReturnType CalculateValues()
{
var result = new MyReturnType();
var config = FirstPrivateOperation();
if ( config == null ) { return result; }
//etc etc
}
public MyReturnType
{
public Whatever A { get;set }
public Whatever B { get;set }
public Whatever C { get;set }
}
you can go even further and deal with the private methods in a different way. you might want to add a separate class to replace them and then that makes theme easier to test / mock as well.
I am currently working on a game in XNA and I'm not sure on how I should go about doing the following...
I have a base class of buildings as such
public class BuildingsBase
{
private int _hp;
public int hp
{
get { return _hp; }
set { _hp= value; }
}
private int _woodRequired;
public int woodRequired
{
get { return _woodRequired; }
set { _woodRequired = value; }
}
}
I then have multiple subclasses for building types eg.
public class TownHall:BuildingsBase
{
public int foodHeld;
public TownHall()
{
foodHeld = 100;
woodRequired = 500;
}
}
My question is, what is the best way of setting the default values for building subclasses.
For example, the woodRequired for a townhall is set to 500 but at various places in code I need to access this value before I have an instance of townhall declared (When checking if there is enough wood to build).
I currently have a global array of default variables for each building type but im wondering if there is a better way of doing this.
if (Globals.buildingDefaults[BuildingType.Townhall].woodRequired < Globals.currentWood)
{
Townhall newTH = new Townhall();
}
Usually what happens is that they create a flyweight (see pattern). This object contains properties that are the same for every instance anyway. There's no need to change (or actually store) the required amount of wood for each instance separately.
In a very basic design it would look like:
class BuildingTemplate
{
public int WoodRequired { get; set; }
}
class Templates
{
public static BuildingTemplate TownHall { get; set; }
}
In the end you'd be calling a method like:
public bool CanBuildTownHall(Player player)
{
return player.HasEnoughResources(Templates.TownHall);
}
Of course, you can use a dictionary for template retrieval, and players shouldn't really know about building requirements. I'm just illustrating the pattern here.
If the player has enough resources, you can use the template to subtract the amount and create an actual instance of the TownHall. It's nice to have an reference to the actual template, because you'd probably be accessing other global properties that are valid for all TownHalls as well (such as audio/visuals/...).
class TownHall
{
public TownHall(BuildingTemplate template)
{
_template = template;
}
}
What I am trying to do is find the most elegant way to create a "pointer-like" class for a specific object/class type that I have in a project.
What I mean is a little confusing without an example. Take this really simple class:
public class MyClass
{
private string _name;
public string GetName() { return _name; }
public void SetName(string name) { _name = name; }
}
I want to create a second class which is like a pointer to it like this:
public class MyClassPtr
{
private MyClass _obj;
public bool IsValid = false;
public MyClassPtr(MyClass obj) { _obj = obj; IsValid = true; }
public void InvalidatePtr()
{
IsValid = false;
obj = null;
}
// SOME MAGIC HERE?
}
The challenge: The key is that I want to elegantly have MyClassPtr provide an interface to all of the public methods/members in MyClass without writing wrappers and/or accessors around each method/member.
I know that I could do this:
public class MyClassPtr
{
public string GetName() { return _obj.GetName(); }
...
}
But that's what I want to avoid. Is there some fundamental abstraction that I don't know of that I can apply to MyClassPtr to allow it to easily re-expose the methods/members in MyClass directed through _obj? I do NOT want MyClassPtr to inherit MyClass. Should MyClassPtr be a type instead, and some trick with accessors to expose the methods/members of MyClass?
Edit: More context on why I am looking for such a design through an example. Here is the overall goal. Imagine a platform that parses through data about people and when it finds information about a person, it creates an instance of Person with that information. You could get a handle to that person like:
Person person1 = platform.GetPerson(based_on_data);
Now, imagine the platform had two instances of Person that it thought were different people, but all of a sudden information came in that strongly suggested those two instances actually refer to the same person. So, the platform wants to merge the instances together in to a new object, let's call it personX.
Now, floating around in the platform someone had a copy of one of those two instances that got merged, which was person1. What I want to do is on-the-fly replace person1 with personX. Literally, I want person1==personX to be true, NOT just that they are two different objects with the same data. This is important since the platform could make a change to personX and unless the two objects are literally equal, a change to personX would not be automatically reflected in person1.
Since I can't on-the-fly replace person1 with personX I had that idea that I wouldn't give direct access to Person, instead I would give access to PersonPtr which the platform (on-the-fly) can change what Person it is pointing to. This would insurance that once person1ptr gets updated to point to personX, if a change is made in personX it will be seen in person1ptr
You could of course use something like
public class MyClassWrapper
{
MyClass _obj;
public MyClassWrapper(MyClass obj)
{
_obj = obj;
}
public void Invoke(Action<MyClass> action)
{
action(_obj);
}
public U Invoke<U>(Func<MyClass, U> func)
{
return func(_obj);
}
public void ChangeTo(MyClass obj)
{
_obj = obj;
}
}
Given your class looks like
public class MyClass
{
public string Name { get; set; }
}
Example:
var person1 = new MyClass { Name = "Instance1" };
var person2 = new MyClass { Name = "Instance2" };
var wrapper = new MyClassWrapper(person1);
wrapper.Invoke(x => x.Name += "original");
var x = wrapper.Invoke(x => x.Name); // Instance1original
wrapper.ChangeTo(person2);
var y = wrapper.Invoke(x => x.Name); // Instance2
but it has a major drawback: you can't access members directly, so you can't bind the data (to a DataTable or a Control).
It would be better to implement all members of your class also in your wrapper class. If you're afraid changes in your class will be forgotten to be implemented in your wrapper, just use an interface:
public interface IMyClass
{
string Name { get; set; }
}
public class MyClass : IMyClass
{
public string Name { get; set; }
}
public class MyClassWrapper: IMyClass
{
MyClass _obj;
public MyClassWrapper(MyClass obj)
{
_obj = obj;
}
public string Name
{
get { return _obj.Name; }
set { _obj.Name = value; }
}
}
Note that regardless which approach you use, you'll have to always keep a reference to the wrapper instance to actually change the underlying instance (using something like static aside).
Also, changing the underlying instance of such a wrapper without telling the component using it that it changed don't seem to be a good idea. Maybe your system is simple enough to get away with a wrapper; that's something you have to decide for yourself.
Maybe your wrapper should simply have an Invalid flag (and/or use an event to signal a change of the underlying object.). Once the underlying object is merged, it is set to true and each member access should throw an exception. This would force the component using the wrapper to deliberately react to changes and to reload the data from your service.
All in all, I think using such a wrapper will just clutter up your code and be error prone (just imagine adding multithreading to the mix). Think twice if you really need this wrapper.
Why not just simply ask your service for a new instance of your class everytime you use it (the service can simply use a cache)? Sure, you can't prevent that someone somewhere keeps a reference; but at least you'll keep your sanity.
I know this has been asked in several different ways, but I am not sure my specific problem has been asked. Due to Business rules, I can not use a db for temp storage of data between views. Static Variables are out (multi-user). I'm trying to avoid session and tempdata. I'll be storing about 9-12 models worth of data that will slow page load if I use Viewstate. I have multi-paged forms that will need to be refilled if the user returns to a form. I know this isn't the ideal way, but can anyone suggest a way to persist this data for multiple models other than session variables? Tempdata would need to be re-written per view I assume. I can't supply code and I know this is not a favorable design, but the rules are constricting.
Thank you.
I don't think there is anything wrong with using Session, even for MVC. It's a tool, use it when you need it. I find that most people tend to avoid Session because the code is usually pretty ugly. I like to use a Generic Wrapper around objects I need to store in session which provide a Strongly-Typed and Re-usable Class (example):
public abstract class SessionBase<T> where T : new()
{
private static string Key
{
get { return typeof(SessionBase<T>).FullName; }
}
public static T Current
{
get
{
var instance = HttpContext.Current.Session[Key] as T;
// if you never want to return a null value
if (instance == null)
{
HttpContext.Current.Session[Key] = instance = new T();
}
return instance;
}
set
{
HttpContext.Current.Session[Key] = value;
}
}
public static void Clear()
{
var instance = HttpContext.Current.Session[Key] as T;
if (instance != null)
{
HttpContext.Current.Session[Key] = null;
}
}
}
Create your class that needs to be stored:
[Serializable] // The only requirement
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Create your Concrete type: (Really really easy?)
public class PersonSession : SessionBase<Person> { }
Use it whenever you want, with whatever you want (as long as it's serializable)
public ActionResult Test()
{
var Person = db.GetPerson();
PersonSession.Current = Person;
this.View();
}
[HttpPost]
public ActionResult Test(Person)
{
if (Person.FirstName != PersonSession.Current.FirstName)
{
// etc, etc
PersonSession.Clear();
}
}