Class designs with collections within them, with collections within those - c#

In a continuation of my previous thread, I have found that a lot of my classes contain collections. Eg:
Engine - contains collection of pistons - piston - contains collection of xyz parts
Thus there is a hierarchy, as every component contains a collection of parts, which goes on and on.
This is a coding scenario I have not come across before. Constantly writing code like so:
class Part (Replace Part with apt name)
{
List<APart> parts ...
}
And then the same for APart, as that contains a collection of inner parts, is very tedious and therefore making me question whether this is the right way to code.
Is there a better way to write this sort of code? Anything like AOP etc I am open to (Though AOP is for cross-cutting concerns).

One thought:
Your Engine class could contain a PistonsManager class, which manages the list of Pistons. The PistonsManager could contain all of the logic to modify the list and shield the Engine class from having to think about Pistons. By the same logic, your PistonsManager class could contain an XYZPartsManager. This way you aren't programming list logic/management into your Engine logic, but have classes to do that. It might make readability and make the logic flow nicely.

Sometimes coding is just tedious. However, there are often patterns that can be ferreted out of an implementation.
We have a situation similar to yours and discovered that there was an underlying recursive pattern. So we implemented a base class (call it Part) that itself can contain a List(Of Part). This can be as deep as needed.
The collection classes for specific class implementations are either generic collections of the specific type or implement an interface that allows us to get at specific data in the class (we had to implement the interface mechanism due to collection collisions in WCF).
The upshot is that you will probably have a lot of discrete Part inheritors, but your will will be a common way to instantiate, process, and traverse your elements with a common set of code.
Update
This is a severely contrived example, but one that should get you pointed in the right direction. In our application, we use a substantial amount of reflection and table-mapped class names in order to severely reduce the amount of repetitive code. This example reflects some of that behavior, but not all.
This example basically shows how you can have a generic part class which contains a recursive collection of parts which are indexed at the part type level. In other words, you will have Engine and Engine will have a collection of part collections indexed by part type. For example, Engine could have a collection of Pistons, a collection of hoses, etc. This design is obviously optional, but does make it somewhat easier to process.
Here are the main classes:
/// <summary>
/// The base part collection
/// </summary>
/// <remarks></remarks>
public class PartBase
{
/// <summary>
/// The key for the record, such as a recordid
/// </summary>
/// <value></value>
/// <returns></returns>
/// <remarks></remarks>
public virtual string CollectionKey {get; set;}
public PartBase() : base()
{
m_cParts = new PartBaseCollections();
}
public virtual void InitializeFromDataRow(DataRow oRow)
{
// ToDo: Either implement generic column/datarow mapping through reflection or have each class override this method
}
private PartBaseCollections m_cParts;
public PartBaseCollections Parts
{
get
{
return m_cParts;
}
}
public PartBaseCollection GetParts(string sTableName)
{
if (this.Parts.Contains(sTableName))
{
return this.Parts(sTableName);
}
else
{
PartBaseCollection cParts = new PartBaseCollection(sTableName);
this.Parts.Add(cParts);
return cParts;
}
}
public void AddParts(DataSet dsData)
{
foreach (DataTable oTable in dsData.Tables)
{
PartBaseCollection cParts = null;
cParts = GetParts(oTable.TableName);
cParts.AddRecordsFromTable(oTable);
}
}
}
/// <summary>
/// A collection of PartBases keyed by a value, such as a table name (for example, Pistons)
/// </summary>
/// <remarks></remarks>
public class PartBaseCollection : System.Collections.ObjectModel.KeyedCollection<string, PartBase>
{
public string CollectionKey {get; set;}
public Type RecordType {get; set;}
public PartBaseCollection(string TableName)
{
this.CollectionKey = TableName;
// Assume that the TableName is a class in the current namespace
RecordType = Type.GetType(this.GetType().Namespace + "." + TableName, false, true);
}
protected override string GetKeyForItem(PartBase item)
{
return item.CollectionKey;
}
public PartBase ManufactureRecord()
{
return Activator.CreateInstance(this.RecordType);
}
public void AddRecordsFromTable(DataTable oTable)
{
foreach (DataRow oRow in oTable.Rows)
{
PartBase oPart = null;
oPart = ManufactureRecord();
oPart.InitializeFromDataRow(oRow);
this.Add(oPart);
}
}
}
/// <summary>
/// All of the PartBaseCollection elements for a given PartBase
/// </summary>
/// <remarks></remarks>
public class PartBaseCollections : System.Collections.ObjectModel.KeyedCollection<string, PartBaseCollection>
{
protected override string GetKeyForItem(PartBaseCollection item)
{
return item.CollectionKey;
}
}
public class Engine : PartBase
{
}
public class Piston : PartBase
{
}
And here is an example of creating the engine:
public void CreateEngine()
{
DataSet dsData = new DataSet();
DataTable oTable = new DataTable("Piston");
dsData.Tables.Add(oTable);
Engine oEngine = new Engine();
oEngine.AddParts(dsData);
}

sounds like the composite design pattern - consider looking at the iterator design pattern and perhaps the visitor design pattern as these usually go together.

Related

Is there any reason to use very simple properties over fields?

I currently have this code written:
public class General
{
/// <summary>
/// Private variables.
/// </summary>
private const float fVersion = 1.3f;
private static bool bMonitoring = false;
/// <summary>
/// Retrieves the current version of the application.
/// </summary>
public static float Version
{
get
{
return fVersion;
}
}
/// <summary>
/// Are we monitoring performance?
/// </summary>
public static bool Monitoring
{
get
{
return bMonitoring;
}
set
{
bMonitoring = value;
}
}
}
In case I check for General.bMonitoring or General.Version often (maybe.. over 100 times a second!) and really care about performance: is it good practice to leave my class written like that, or should I simply delete these properties and make the fields public?
In this case if you aren't going to add some logic to the getter or setter then I would use static fields. Performance will be the same.
But if later you need extra logic when you set ot get values then it preffer to use properties because it allows for versioning and it gives you Encapsulation according to OOP principles. Don't care about performance
For Monitoring property you can use Auto-Implemented Property like
public static bool Monitoring { get; set; }
but in this case you need to implement a static constructor (thanks to #Mafii)
static General()
{
Monitoring = false;
}
or if you use C# 6.0 then just:
public static bool Monitoring { get; set; } = false;
Don't worry about performance. Property access is (and should be) very fast and compiler may inline them.
Property is preferred over field not because of performance, but because encapsulation and it will really helps when later you need for example checking or make property computed.
More by Jon Skeet http://csharpindepth.com/Articles/Chapter8/PropertiesMatter.aspx

Cant access a public variable from a public class anywhere in my solution (VS, C'#)

i have taken over a project and I am struggling to access a public variable from a public class. (Strange).
I am relatively new to C# having only done some MVC, ASP.NET stuff so i dont know if im being a bit of a clown but:
public int AlertCount
{
get { return Convert.ToInt32(alertCountTextBlock.Text); }
set { alertCountTextBlock.Text = value.ToString(); }
}
/// <summary>
/// Property which represents the number of new alerts the project currently has
/// </summary>
public int NewAlertCount
{
get { return Convert.ToInt32(newAlertCountTextBlock.Text); }
set { newAlertCountTextBlock.Text = value.ToString(); }
}
These are the two variables i am trying to access from another class inside my solution (above)
namespace Intelligence_Gathering_System.Pages.Project.Controls
{
/// <summary>
/// UserControl which acts as a selection button for each project. It displays the projects name and
/// current alert item totals along with providing methods for sharing and selecting of the project
/// </summary>
public partial class ProjectHeaderControl
{
private readonly ProjectPage _parentReference; //Reference to the controls 'parent' Project Page
/// <summary>
/// Overloaded constructor which initialises the controls members
/// </summary>
/// <param name="projectName">The name of the project</param>
/// <param name="alertCount">The total number of Alert Items in the project</param>
/// <param name="newAlertCount">The total numebr of New Alert Items in the project</param>
/// <param name="parent">A reference to the controls 'parent' Project Page</param>
public ProjectHeaderControl(string projectName, int alertCount, int newAlertCount, ProjectPage parent)
{
this is the class structure (namespace, partial class and constructor) which the variables reside,
I am simply trying to call from another piece of code (within the same solution and project ) to alter a count to increment and decrement
I have tried inside the class i need to increment and decrement (there are multiple classes i need to do this) putting the full namespace path then the variable to pinpoint it exacty and the class. variable (example of one seen below)
int x = Intelligence_Gathering_System.Pages.Project.Controls.NewAlertCount;
or
int x = ProjectHeaderControl.NewAlertCount;
neither of them are working and im a bit baffled as to why.
Am i missing something obvious here or....
Is it syntax related due to C# i'm unsure.
Any help would be appreciated.
Regards
Jordan
NewAlertCount is a property in a class - but we can't tell what that class is. (Maybe it's ProjectHeaderControl - your description is somewhat hard to understand.)
Intelligence_Gathering_System.Pages.Project.Controls is a namespace. A namespace can't declare properties.
You need to specify the class which contains the properties - and they'll either need to be static properties, or you'll need to fetch the property from an instance of the class.

Windsor circular dependency of a transient-lifestyle component

I've got a bunch of classes written like this:
public class MyService1 {
public MyService1(MyService1Settings settings, <service-dependent list of dependencies filled by Windsor>) { ... }
}
which are registered in the Windsor like this:
container.Register(
...
Component.For<MyService1>().LifestyleTransient(),
Component.For<MyService2>().LifestyleTransient(),
...
);
container doesn't have any of the MyServiceXSettings types registered, so the only way to get a service is to resolve it from container like this:
TService service = windsorContainer.Resolve<TService>(new { settings });
The thing is, depending on the parameters in the settings object, one of the services tries to acquire another instance of its type with different settings object.
Something along the lines of:
public class MyService2 {
public MyService2(MyService2Settings settings, <service-dependent list of dependencies filled by Windsor>)
{
this.uplink = settings.Counter == 1
? new AnotherUplink()
: new RecursiveUplink(
container.Resolve<MyService2>(new {
settings = new MyService2Settings(settings.Counter - 1)
});
}
}
This recursive dependency chain is finite (and is about 6 instances deep), but Windsor throws an exception when the first service tries to get another one, stating that it's a circular dependency.
I've advertised all the services as having Transient lifestyles and requesting them with custom parameters. Can I at least specify the maximum allowed depth of the recursion? Or am I missing another way I can do it?
another requirement: I can't use typed factories, because I've got quite many different types of those services, so generating many factory interfaces individually for those services would be undesired.
container doesn't have any of the MyServiceXSettings types registered,
so the only way to get a service is to resolve it from container like
this:
You may also use a dedicated SubResolver or a DependsOn during component registration.
Executing code in a constructor(rather than a simply variable assignement) is a smell, even worst using the container: it should never leak in the application layer.
At the first sight, it seems you are using the settings only to choose the proper component within the constructor: that should be done at CompositionRoot, using a TypedFactory or also by naming convention(you may have multiple component registered for same intercace, but a given parameter name drives the component selection)
As per this answer, I went with lazy resolution.
/// <summary>
/// Represents single component instance producer.
/// </summary>
/// <typeparam name="TComponent">type of the component to create</typeparam>
public interface IComponentCreator<TComponent>
{
/// <summary>
/// Gets the created component.
/// </summary>
TComponent Component { get; }
}
/// <summary>
/// Creates the component only when it's first requested.
/// </summary>
/// <typeparam name="TComponent">type of the component to create</typeparam>
public class LazyCreator<TComponent> : IComponentCreator<TComponent>
{
private readonly Func<TComponent> creatingFunction;
private bool created;
private TComponent component;
public LazyCreator(Func<TComponent> creatingFunction)
{
this.creatingFunction = creatingFunction;
}
public TComponent Component
{
get
{
if (!created)
{
component = creatingFunction();
created = true;
}
return component;
}
}
}
/// <summary>
/// Returns already created component.
/// </summary>
/// <typeparam name="TComponent">type of the component</typeparam>
public class ComponentContainer<TComponent> : IComponentCreator<TComponent>
{
private readonly TComponent component;
public ComponentContainer(TComponent component)
{
this.component = component;
}
public TComponent Component
{
get { return component; }
}
}

Function returning list of different possible children classes

I have a binding source which can be bound to a list of A or a list of B. Depending if it's A or B, when I click "Save" I want to call the save method of the appropriate repository.
I was able to create this method to check if any list is dirty and needs saving:
private static bool IsDirty<T>(TList<T> list) where T : IEntity, new()
{
foreach (var entity in list)
{
if (entity.IsDirty)
return true;
}
return false;
}
However, I am having a problem with the following:
var list = CurrentTList<A>();
and
private TList<T> CurrentTList<T>() where T: IEntity, new()
{
switch (currentRatesTable)
{
case RatesTables.A:
return (TList<T>) _bindingSourceMaster.List;
case RatesTables.B:
return (TList<T>) _bindingSourceMaster.List;
default:
return null;
}
}
Is this the best way to get my current list from the data source? I would like to avoid using a switch like so, as it doesn't look right to me:
switch (currentRatesTable)
{
case Form1.RatesTables.A:
var list = CurrentTList<A>();
case Form1.RatesTables.B:
var list = CurrentTList<B>();
// ...
}
Yeah, as Sayse says, you need yourself an interface and/or an abstract class. If there's a lot of shared code, you can just start with the latter. Here's something riffed on from an old test project. It takes a different approach (each item in the collection is what's relevant as the 'dirty' thing, and there are excised methods that would search the collection for those), but you should be able to adapt as needed:
[DataContract]
public abstract class Dirty : Object
{
protected bool _isdirty;
public bool IsDirty
{
get { return _isdirty; }
set
{
_isdirty = value;
}
}
public abstract class DataStore<T> where T : Dirty
{
private string _path;
private string _tempFile;
protected DataStore(string path, string tempfile)
{
_path = path;
_tempFile = tempfile;
}
}
So DataStore held the logic to manipulate those lists. The idea for me was both classes that inherited from Dirty were being serialized to JSON, so as long as their members had the right attributes they all got properly serialized, and thus there was no custom logic for each class for its storage. Thus, all they had to do to create their datastore was:
[DataContract]
public class Account : Abstracts.Dirty
{
#region DataStore fields and singleton
private static volatile StoreClass _store = new StoreClass();
protected static StoreClass Store
{
get
{
return _store;
}
}
/// <summary>
/// Store is the data store for the Account class. This holds the active list of Accounts in a singleton, and manages the push/pull to the JSON file storage.
/// </summary>
protected class StoreClass : Abstracts.DataStore<Account>
{
#region Singleton initialization and Constructor
public StoreClass()
: base("accounts.json", "TEMP_accounts.json")
{
}
#endregion
}
}
I cut out a few thousand lines on this project just from the datastore, but it was pretty crazy. The basic idea is to build the logic you need into the DataStore class to save a list, and aim how you save/load it via how you call its constructor from the StoreClass child.

Getter and Setter in generic interface - is this possible?

Still learning my ways around C# generics... is it possible to achieve this functionality?
public interface ISetting<T>
{
void SetSettings(T obj);
// myTypeHere GetSettings(T obj);
}
public class RadDockSetting : ISetting<CormantRadDock>
{
public RadDockSetting()
{
}
public RadDockSetting GetSettings(CormantRadDock dock)
{
}
public void SetSettings(CormantRadDock dock)
{
}
}
I realize this is a counter-intuitive way to be using a Getter -- shouldn't have to pass anything to it. What I'm doing is creating an object, RadDockSetting, that stores the relevant properties of the CormantRadDock -- and then returns the 'got' settings.
GetSettings is currently a static method, but I realize this will need to be refactored in order to allow implementing a getter from the interface. Maybe once this occurs the 'weirdness' of the getter will fall away?
So, a little background on all of this:
I started with a class that had a lot of 'copy/pasted' functions. These functions were in charge of saving and removing controls from a manager. When I realized this I set out trying to make these functions more generic. I succeeded, with SO's help, in making remove generic.
For reference, here is remove:
public static void Remove<T>(string controlID) where T: new()
{
Logger.InfoFormat("Removing control {0}", controlID);
T states = RadControlStates.GetStates<T>();
(states as IDictionary).Remove(controlID);
RadControlStates.SetStates<T>(states);
}
and it is called like so: RadControlSave.Remove<SerializableDictionary<string, RadPaneSetting>>(ID);
Now, I am trying to extend this genericness to the rest of the methods -- the savers. Here's how one of these methods looks currently:
public static void SavePane(CormantRadPane pane)
{
Logger.InfoFormat("Saving pane {0}", pane.ID);
RadPaneSetting paneSettings = RadPaneSetting.GetSettings(pane);
SerializableDictionary<string, RadPaneSetting> paneStates = RadControlStates.GetStates<SerializableDictionary<string, RadPaneSetting>>();
bool paneIsKnown = paneStates.ContainsKey(paneSettings.ID);
if (paneIsKnown)
{
Logger.Debug("Pane is known. Overwriting data.");
paneStates[paneSettings.ID] = paneSettings;
}
else
{
Logger.Debug("Pane is unknown. Saving data.");
paneStates.Add(paneSettings.ID, paneSettings);
}
RadControlStates.SetStates<SerializableDictionary<string, RadPaneSetting>>(paneStates);
}
At the start of this code block there is a call to "RadPaneSetting.GetSettings(pane)".
RadPaneSettings implements the ISettings interface. Here is ISetting's setter being used.
/// <summary>
/// Recreates a dashboard control based off of its settings.
/// </summary>
/// <typeparam name="T"> The type of control to be recreated. </typeparam>
/// <param name="settings"> The known settings needed to recreate the control.</param>
/// <returns> The recreated control. </returns>
public static T Recreate<T>(ISetting<T> settings) where T : new()
{
T _control = new T();
settings.SetSettings(_control);
Logger.DebugFormat("Recreated control {0}", (_control as Control).ID);
return _control;
}
It looks like you just need to add another generic parameter here
public interface ISetting<T1, T2>
{
void SetSettings(T1 obj);
T2 GetSettings(T1 obj);
}
public class RadDockSettings : ISetting<CormantRadDock, RadDockSetting>
Your question is not very clear but do you need a property:
public interface ISetting<T>
{
T Setting { get; set; }
}
public class RadDockSetting : ISetting<CormantRadDock>
{
public CormantRadDock Setting { get; set; }
}
What you have would work if you define another generic parameter (as #jaredPar pointed out). You may want to consider using Extension Methods rather than the class approach, though. It would allow you to have a "cleaner" API for getting the settings.
Sample:
public static class RadDockExtensions
{
public static RadDockSetting GetSettings(this CormantRadDock dock)
{
// Implementation
}
}
Or if you want something more generic
public static class RadDockExtensions
{
public static U GetSettings<T,U>(this T dock)
{
// Implementation
}
}
Though in this case you would need to add some constraints to actually create the implementation
It's not entirely clear to me what the purpose of the SetSettings method is, since you appear to be sending in the same object your sending to GetSettings.
In both cases you would use the above code like this:
RadDockSetting mySettings = myDock.GetSettings();
hmmmm might have missed the point.
but why would a settings class have a getSettings call? would it just return this?
The set takes a dock to initialise the instance, then get is merely the instance.
I'm not really sure what you want to do.
Maybe an extension method could do the trick rather than a method inside the interface ISetting... something like that :
public static T GetSettings<T,C>(this T t, C c) where T : ISetting<C>
{
return t;
}
Hope this helps...

Categories