Subclassing dictionary for use in external components - c#

I have a dictionary class which is used to store data, and which tracks hundreds of variables during the course of a session.
I have been tasked with building a common framework, which I can reference this base set of functionality, but allow the calling components to use different key and value within the dictionary.
Currently, this dictionary uses a 4-part tuple as the key, and a 2-part value.
The two components I'm tying into has a different key and value layout.
Component 1 - key is a 5-part tuple, and value is a 3-part.
Component 2 - Key is a 3-part tuple (string, int, string) and the same 2-part value.
This class handles data transfer to other components, so to avoid duplication of effort, want to keep as much of the common functionality in the Common dll, and external components would use the Survey class which the different key/value. Not certain I'm explaining it well enough.
I have included the current code below.
Seems to me, if the main Survey is created with object, object, and subclass the external components with the correct key/value pair.
public sealed class Survey
{
#region Private Objects
private Survey()
{
}
private Dictionary<SurveyKey, SurveyValue> survey = new Dictionary<SurveyKey, SurveyValue>();
private int maxLines = 50000;
private bool AllowLogging { get => (survey.Count > maxLines); }
#endregion
private void WriteData(SurveyKey key, SurveyValue value)
{
if (AllowLogging)
{
if (!survey.ContainsKey(key))
survey.Add(key, value);
else
survey[key] = value;
}
}
}
#region SurveyValue Class
public sealed class SurveyValue
{
public SurveyValue(int? value = null, string detail = null)
{
Detail = detail;
Value = value;
}
// Uses an either/or value; Value or Detail
public string Detail { get; private set; }
public int? Value { get; private set; }
}
#endregion
#region SurveyKey Class
public sealed class SurveyKey : Tuple<string, string, string, string>
{
public SurveyKey(string Signal, string SignalType, string Name, string OverallType) : base(Signal, SignalType, Name, OverallType) { }
public string Signal { get => Item1; }
public string SignalType { get => Item2; }
public string Name { get => Item3; }
public string OverallType { get => Item4; }
}

Make your common class generic of type K,V and use the where keyword to restrict the dictionary K and V to KBaseClass and VBaseClass. Component1 can expose KBaseClass and VBaseClass derived types and inherit from common or reuse common.

Turns out, I was over thinking this problem. All I need to do is create my base dictionary as Survey, and use this in my external components.
For some reason I was thinkning I needed to create an interface to allow the plugging in of the base dictionary.
private Dictionary<TKey, TValue> survey = new Dictionary<TKey, TValue>();

Related

C# Subclass Best Practice

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;
}
}

Alternative to nesting enums

I'm trying to create several enums as such, that gives the syntax of Dropdown.Category.Subcategory. However, I have been reading that this isn't such a good idea. My choice for this was mostly because I couldn't think of any other way to select different enum values depending on the choice of the category, and then the choice of the subcategory is subject to the selected enum based on the enum values.
Is there a better way to create such functionality? I would prefer to be able to easily identify both the .Category and .Subcategory names, and it would be a bonus if this code was readable.
Just to make it clear, I want to be able to choose the Category, then have an appropriate Subcategory selection.
public class Dropdown
{
public enum Gifts
{
GreetingCards,
VideoGreetings,
UnusualGifts,
ArtsAndCrafts,
HandmadeJewelry,
GiftsforGeeks,
PostcardsFrom,
RecycledCrafts,
Other
}
public enum GraphicsAndDesign
{
CartoonsAndCaricatures,
LogoDesign,
Illustration,
EbookCoversAndPackages,
WebDesignAndUI,
PhotographyAndPhotoshopping,
PresentationDesign,
FlyersAndBrochures,
BusinessCards,
BannersAndHeaders,
Architecture,
LandingPages,
Other
}
}
Create a class that cannot be inherited from externally, give it several inner classes, each extending from it. Then add static read only variables for each of the values that you want to represent:
public class Dropdown
{
private string value;
//prevent external inheritance
private Dropdown(string value)
{
this.value = value;
}
public class Gifts : Dropdown
{
//prevent external inheritance
private Gifts(string value) : base(value) { }
public static readonly Dropdown GreetingCards =
new Gifts("GreetingCards");
public static readonly Dropdown VideoGreetings =
new Gifts("VideoGreetings");
public static readonly Dropdown UnusualGifts =
new Gifts("UnusualGifts");
public static readonly Dropdown ArtsAndCrafts =
new Gifts("ArtsAndCrafts");
}
public class GraphicsAndDesign : Dropdown
{
//prevent external inheritance
private GraphicsAndDesign(string value) : base(value) { }
public static readonly Dropdown CartoonsAndCaricatures =
new GraphicsAndDesign("CartoonsAndCaricatures");
public static readonly Dropdown LogoDesign =
new GraphicsAndDesign("LogoDesign");
public static readonly Dropdown Illustration =
new GraphicsAndDesign("Illustration");
}
public override string ToString()
{
return value;
}
}
In this case every single value is actually an instance of type Dropdown, so you could have, say, a parameter to a method that accepts a Dropdown instance. With enums there is no way to say, "I want to accept any of the enums declared in the Dropdown class."
Here is some example usage:
public static void UseDropdown(Dropdown type)
{
if (type is Dropdown.Gifts)
{
if (type == Dropdown.Gifts.GreetingCards)
{
DoStuff();
}
}
else if (type is Dropdown.GraphicsAndDesign)
{
}
}
You could also have a parameter that accepts an object of type Gifts or GraphicsAndDesign, if you only want a sub-type to be valid in some context.
Sadly, using this solution there's no good way to switch on a dropdown value; you have to just use if/else if chains to check the values.
The use of an instance string value may not be required (see the first revision for a version without it) but it can be very helpful to be able to have a meaningful string value (or other kind of value; you can associate an integer, a byte, or whatever with each enumeration value).
The Equals and GetHashCode implementations should be meaningful if left without being overridden.
You can implement IComparable if the items should be logically ordered somehow, like real enums.

Following the DRY principle in ASP.NET

I have just recently got involved in a classic ASP.NET project which contains lots of storing and reading values from the session and query strings. This could look something like the following:
Session["someKey"]=someValue;
And somewhere else in the code the value in the session is read. Clearly this violates the DRY principle since you'll have the literal string key spread out all over the code. One way to avoid this could be to store all keys as constants that could be referenced everywhere there is a need to read and write to the session. But I'm not sure that's the best way to do it. How would you recommend I best handle this so that I don't violate the DRY principle?
Create a separate public class where you can define your constants, e.g
public class SessionVars
{
public const string SOME_KEY = "someKey";
public const string SOME_OTHER_KEY = "someOtherKey";
}
and then anywhere in your code you can access session variables like this:
Session[SessionVars.SOME_KEY]=someValue;
This way you can get IntelliSence and other bells and whistles.
I think you're reading too much into DRY. I pertains more to things that could be wrapped up in a function. I.e. instead of repeating the same fives lines all over the place wrap those 5 lines in a function and call the function everywhere you need it.
What you have as an example is just setting a value in a dictionary (the session object in this case), and that is the simplest way to store and retrieve objects in it.
I can't remember for the life of me where I humbly re-purposed this code from, but it's pretty nice:
using System;
using System.Web;
namespace Project.Web.UI.Domain
{
public abstract class SessionBase<T> where T : class, new()
{
private static readonly Object _padlock = new Object();
private static string Key
{
get { return typeof(SessionBase<T>).FullName; }
}
public static T Current
{
get
{
var instance = HttpContext.Current.Session[Key] as T;
lock (SessionBase<T>._padlock)
{
if (instance == null)
{
HttpContext.Current.Session[Key]
= instance
= new T();
}
}
return instance;
}
}
public static void Clear()
{
var instance = HttpContext.Current.Session[Key] as T;
if (instance != null)
{
lock (SessionBase<T>._padlock)
{
HttpContext.Current.Session[Key] = null;
}
}
}
}
}
The idea behind it two fold. The type created should be the only type you need. It's basically a big strongly-typed wrapper. So you have some object you want to keep extending information in:
public class MyClass
{
public MyClass()
public string Blah1 { get; set; }
}
Then down the road you extend MyClass and you don't want to have to remember all the Key Values, store them in AppSettings or Const variables in Static Classes. You simply define what you want to store:
public class MyClassSession : SessionBase<MyClass>
{
}
And anywhere in your program you simply use the class.
// Any Asp.Net method (webforms or mvc)
public void SetValueMethod()
{
MyClassSesssion.Current.Blah1 = "asdf";
}
public string GetValueMethod()
{
return MyClassSession.Current.Blah1;
}
Optionally you could place the access to this session object in a base page and wrap it in a property:
class BasePage : Page
{
...
public string MySessionObject
{
get
{
if(Session["myKey"] == null)
return string.Empty;
return Session["myKey"].ToString();
}
set
{
Session["myKey"] = value;
}
}
...
}
Here you are repeating the myKey string but it is encapsulated into the property. If you want to go to the extreme of avoiding this, create a constant with the key and replace the string.

C# Expose strongly typed dictionary keys

I am sure I am not going to use the correct words to explain but I hope you understand what I am trying to accomplish.
I have a class that gets passed in dictionary collection. Is it mandatory that this passed in dictionary collection has certain keys that this class needs. I would like to be able to expose publicly those keys needed by the class, but not just as strings, but actual items. An enumeration would work but since this class is a base class I dont think that is a good solution. I need something similar to the Resources class that is generated everytime you add items to the Resources.resx file. So you that you can just go to Resources.Resources.MyLabel1, Resources.Resources.MyLabel2, etc.
Is this possible?
Thanks,
Mike
Create properties that expose your values
public class MyClass
private Dictionary<string,string> _dict;
public MyClass (Dictionary<string,string> dict)
{
_dict = dict;
}
public string FirstName { get { return _dict["FirstName"]; } }
public string LastName { get { return _dict["LastName"]; } }
...
}
Alternatively you can aslo create read/write properties
public string FirstName {
get { return _dict["FirstName"]; }
set { _dict["FirstName"] = value; }
}
You could just offer a static or const member on your class:
class PickyClass {
public static readonly string[] RequiredKeys = new[] {"length", "width"};
/// <summary>
/// Please note that you must include at least RequiredKeys in values
/// </summary>
public void Setup(Dictionary<string,string> values)
{
...
}
}
(edit) or is it important that they are addressable by name? In which case, how about:
class PickyClass {
public class RequiredKeys
{
public const string Length = "length";
public const string Width = "width";
}
/// <summary>
/// Please note that you must include every const in RequiredKeys in values
/// </summary>
public void Setup(Dictionary<string,string> values)
{
...
}
}
This sounds like a detail you should hide
public void Setup(Dictionary<string,string> values)
If values must contain certain keys, then maybe you could encode that information in your own dictionary type.
public class FussyDictionary : Dictionary<string,string> {
// You must provide these values
public FussyDictionary(string valueA, string valueB) {
Add("magicKey1", valueA);
Add("magicKey2", valueB);
}
// Override remove to stop you removing these keys?
}

C# Accessors and Collections

When defining classes I expose class members as properties along the lines of :
class ClassA
{
private String _Name;
public String Name
{
get { return _Name; }
set { _Name = value; }
}
}
What is best practice for dealing with collections within classes, with respect to accessors
So if the class is extended to something like :
class ClassA
{
private String _Name;
private List<String> _Parts = new List<String>();
public String Name
{
get { return _Name; }
set { _Name = value; }
}
}
How do I expose the next item?
Expose a read-only instance of the collection. Note that the contents are not read-only, but the reference is.
public IList<String> Parts { get; private set; }
The naming conventions I've come across recommend
private String _name;
Also you could use automatic properties which generate the same code you've written
public string Name {get; set;}
For collections, I don't like to expose the actual collection but methods to work on it.
public void Add(...
public void Remove(...
Otherwise you could make it readonly with an automatic property
public IList<string> Parts {get; private set;}
I don't know if there is specifically a best practice in place, but there are a couple things to consider. The basic approach is the same as what others have stated:
public List<String> Parts
{
get { return _Parts; }
private set { _Parts = value; }
}
The important point here is to make sure that _Parts is never null. That leads to subtle and hard to discover bugs.
However, if you need to send events when elements are added and removed you have only two options:
Use a subclass of List that sends the events when appropriate
Don't expose the List at all, and merely expose the AddPart(), RemovePart(), and ListParts() (that returns a copy of the current list).
If your needs are simple, just expose the property (but protect it from being assigned null). Otherwise you'll have to be a bit more fancy.
It depends on how serious you are about encapsulating the way the data is stored. If you're doing a lightweight class and you are just providing the storage but want to leave the accessing decisions completely up to the consumer of your class, you just expose it like a standard property or make it an auto-property.
public List<String> Parts { get; private set; }
If you want to ensure the variable is never null, continue to use your private backing field and add checks.
private List<String> _Parts;
public IList<String> Parts
{
get
{
if (_Parts == null)
_Parts = new List<String>();
return _Parts;
}
private set
{
if (value != null)
_Parts = value;
}
}
If, however, you want to control synchronization, or anything else of that sort, you'd expose methods that are logical for what you're doing.
public void AddPart(String part);
public void RemovePart(String part);
public String GetPart(int index);
public IEnumerable<String> GetAllParts()
{
foreach(String part in _Parts)
yield return part;
}
Couldn't you just do the same - but for the list?
public List<String> parts
{
get { return _Parts; }
set { _Parts = value; }
}
I would expose as property as well
public List<string> Parts { get; set; }
You have a bunch of options and it really depends on what kind of operations you want to open up to the public API of your class. The most common approaches are:
Provide a readonly property to returns the actual collection instance with the same type information.
Provide a readonly property that returns an IEnumerable interface.
Provide a readonly property that returns a ReadOnlyCollection wrapper of the collection.
Again, it really depends on how you want to expose the collection, but the 3 options above will work fine in most scenarios. If you have more specialized requirements like allowing additions to the collection from the public API while at the same time disallowing removals then things get a bit more complicated.
We typically do the following:
private Collection<String> _parts = new Collection<String>();
public Collection<String> Parts {
get { return _parts; }
}
This ensures that the collection is instantiated when the object is created and it makes the underlying reference for the _parts collection read only. Which means you can add/remove parts but you can't change what the property points to.

Categories

Resources