How to design these classes the best way? - c#

I have a question how to design the following case in a good (better) model (I'm using C#):
So far it is like this:
public class ExampleClass
{
private object ExampleClassPrivate;
public SubExampleClass SubExampleClassPublic;
-------
public void ChangeExampleClassPrivate()
{
ExampleClassPrivate = "SOMETHING";
}
private class SubExampleClass
{
private object SubExampleClassPrivate;
public SubSubExampleClass SubSubExampleClassPublic;
.
.
.
}
public class SubSubExampleClass
{
...
public void DoSomething()
{
//Do something within SubSubExampleClass
//In the end: call ChangeExampleClassPrivate()
}
}
}
I could do the following:
I create an instance of ExampleClass, let's call it "TestInstance".
Then:
TestInstance.SubExampleClassPublic.SubSubExampleClassPublic.DoSomething();
TestInstance.ChangeExampleClassPrivate();
But I don't want to execute ChangeExampleClassPrivate() manually the whole time after DoSomething(). I look for a possibility to call ChangeExampleClassPrivate() from inside of DoSomething().
How could I achieve this? I guess my class structure is not perfect, but i don't see how I could change it to work the proper way.

You can pass a reference to a prent class to all your subclasses, like this:
private class SubExampleClass
{
private object SubExampleClassPrivate;
private readonly SubSubExampleClass SubSubExampleClassPublic;
private readonly ExampleClass parent;
public SubExampleClass(ExampleClass parent)
{
// save reference to the parent object
this.parent = parent;
// pass it to subclass
SubSubExampleClassPublic= new SubSubExampleClass(parent)
}
.
.
.
}
public class SubSubExampleClass
{
private readonly ExampleClass parent;
public SubSubExampleClass(ExampleClass parent)
{
this.parent = parent; // save reference to the parent object
}
public void DoSomething()
{
//Do something within SubSubExampleClass
parent.ChangeExampleClassPrivate;
}
}
And a usage, somewhere in ExampleClass:
var instance = new SubExampleClass(this);
instance.SubSubExampleClassPublic.DoSomething();

Related

Implementing multiple behaviors on a child class from a method on a root class

I'm looking to implement a certain behavior but I'm not sure how to implement it.
Given a base class :
public class Base
{
void Start() { }
void Update() { }
}
And these two classes which inherit it.
public class Behavior1 : Base
{
private int member;
void Start() { member = 0; }
void Update() { member++; }
}
public class Behavior2 : Base
{
private string name;
void Start() { name = "some string"; }
void Update() { if(name) { Console.WriteLine(name) } }
}
And then a final class which I wish to inherit the logic of the two sub classes.
public class Child : Base // ? Behavior1, Behavior2
{
void Start() { } // logic and members implemented but don't need to be referenced
void Update() { }
}
How would I go about having the Child class implement the two Behavior classes? I don't think you can inherit more than one class at a time so I can't do that. Is there another construct which can accomplish this?
Wihtout enter to valorate the inheritance, that probably need some think as you can read in the comments, you can do something like this if you want use both behaviors ni a class that doesn't inherith them:
public class Child : Base
{
private readonly Behavior1 _behavior1;
private readonly Behavior2 _behavior2;
public Child()
{
this._behavior1 = new Behavior1();
this._behavior2 = new Behavior2();
}
public override void Start()
{
this._behavior1.Start();
}
public override void Update()
{
this._behavior2.Update();
}
}
You can also inherith from Behavior1 and only add Behavior2 as a field:
public class Child : Behavior1
{
private readonly Behavior2 _behavior2;
public Child()
{
this._behavior2 = new Behavior2();
}
public override void Update()
{
this._behavior2.Update();
}
}
But, as I said, is probably that you find a better solution thinking about your models and their composition/inheritance.

Passing a generic <TObject> class to a form

I can't seem to find out the answer to this through searching, so here goes....
I know that I can pass Class objects generically to other classes by utilising this type of code:
public class ClsGeneric<TObject> where TObject : class
{
public TObject GenericType { get; set; }
}
Then constructing in this way:
ClsGeneric<MyType> someName = new ClsGeneric<MyType>()
However, I have an application that requires me to open a Form and somehow pass in the generic type for use in that form. I am trying to be able to re-use this form for many different Class types.
Does anyone know if that's possible and if so how?
I've experimented a bit with the Form constructor, but to no avail.
Many thanks in advance,
Dave
UPDATED: A Clarification on what the outcome I am trying to achieve is
UPDATED: 4th AUG, I've moved on a little further, but I offer a bounty for the solution. Here is what I have now:
interface IFormInterface
{
DialogResult ShowDialog();
}
public class FormInterface<TObject> : SubForm, IFormInterface where TObject : class
{ }
public partial class Form1 : Form
{
private FormController<Parent> _formController;
public Form1()
{
InitializeComponent();
_formController = new FormController<Parent>(this.btnShowSubForm, new DataController<Parent>(new MeContext()));
}
}
public class FormController<TObject> where TObject : class
{
private DataController<TObject> _dataController;
public FormController(Button btn, DataController<TObject> dataController)
{
_dataController = dataController;
btn.Click += new EventHandler(btnClick);
}
private void btnClick(object sender, EventArgs e)
{
showSubForm("Something");
}
public void showSubForm(string className)
{
//I'm still stuck here because I have to tell the interface the Name of the Class "Child", I want to pass <TObject> here.
// Want to pass in the true Class name to FormController from the MainForm only, and from then on, it's generic.
IFormInterface f2 = new FormInterface<Child>();
f2.ShowDialog();
}
}
class MeContext : DbContext
{
public MeContext() : base(#"data source=HAZEL-PC\HAZEL_SQL;initial catalog=MCL;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework") { }
public DbSet<Parent> Child { get; set; }
}
public class DataController<TObject> where TObject : class
{
protected DbContext _context;
public DataController(DbContext context)
{
_context = context;
}
}
public class Parent
{
string Name { get; set; }
bool HasChildren { get; set; }
int Age { get; set; }
}
public class Child
{
string Name { get; set; }
int Age { get; set; }
}
Maybe you've tried this, but you can create a custom class:
public class GenericForm<TObject> : Form where TObject : class
{
// Here you can do whatever you want,
// exactly like the example code in the
// first lines of your question
public TObject GenericType { get; set; }
public GenericForm()
{
// To show that this actually works,
// I'll handle the Paint event, because
// it is executed AFTER the window is shown.
Paint += GenericForm_Paint;
}
private void GenericForm_Paint(object sender, EventArgs e)
{
// Let's print the type of TObject to see if it worked:
MessageBox.Show(typeof(TObject).ToString());
}
}
If you create an instance of it like that:
var form = new GenericForm<string>();
form.Show();
The result is:
Going further, you can create an instance of type TObject from within the GenericForm class, using the Activator class:
GenericType = (TObject)Activator.CreateInstance(typeof(TObject));
In this example, since we know that is a string, we also know that it should throw an exception because string does not have a parameterless constructor. So, let's use the char array (char[]) constructor instead:
GenericType = (TObject)Activator.
CreateInstance(typeof(TObject), new char[] { 'T', 'e', 's', 't' });
MessageBox.Show(GenericType as string);
The result:
Let's do the homework then. The following code should achieve what you want to do.
public class Parent
{
string Name { get; set; }
bool HasChildren { get; set; }
int Age { get; set; }
}
public class Child
{
string Name { get; set; }
int Age { get; set; }
}
public class DataController<TObject> where TObject : class
{
protected DbContext _context;
public DataController(DbContext context)
{
_context = context;
}
}
public class FormController<TObject> where TObject : class
{
private DataController<TObject> _dataController;
public FormController(Button btn, DataController<TObject> dataController)
{
_dataController = dataController;
btn.Click += new EventHandler(btnClick);
}
private void btnClick(object sender, EventArgs e)
{
GenericForm<TObject> form = new GenericForm<TObject>();
form.ShowDialog();
}
}
public class GenericForm<TObject> : Form where TObject : class
{
public TObject GenericType { get; set; }
public GenericForm()
{
Paint += GenericForm_Paint;
}
private void GenericForm_Paint(object sender, EventArgs e)
{
MessageBox.Show(typeof(TObject).ToString());
// If you want to instantiate:
GenericType = (TObject)Activator.CreateInstance(typeof(TObject));
}
}
However, looking to your current example, you have two classes, Parent and Child. If I understand correctly, those are the only possibilities to be the type of TObject.
If that is the case, then the above code will explode if someone pass a string as the type parameter (when the execution reaches Activator.CreateInstance) - with a runtime exception (because string does not have a parameterless constructor):
To protect your code against that, we can inherit an interface in the possible classes. This will result in a compile time exception, which is preferable:
The code is as follows.
// Maybe you should give a better name to this...
public interface IAllowedParamType { }
// Inherit all the possible classes with that
public class Parent : IAllowedParamType
{
string Name { get; set; }
bool HasChildren { get; set; }
int Age { get; set; }
}
public class Child : IAllowedParamType
{
string Name { get; set; }
int Age { get; set; }
}
// Filter the interface on the 'where'
public class DataController<TObject> where TObject : class, IAllowedParamType
{
protected DbContext _context;
public DataController(DbContext context)
{
_context = context;
}
}
public class FormController<TObject> where TObject : class, IAllowedParamType
{
private DataController<TObject> _dataController;
public FormController(Button btn, DataController<TObject> dataController)
{
_dataController = dataController;
btn.Click += new EventHandler(btnClick);
}
private void btnClick(object sender, EventArgs e)
{
GenericForm<TObject> form = new GenericForm<TObject>();
form.ShowDialog();
}
}
public class GenericForm<TObject> : Form where TObject : class, IAllowedParamType
{
public TObject GenericType { get; set; }
public GenericForm()
{
Paint += GenericForm_Paint;
}
private void GenericForm_Paint(object sender, EventArgs e)
{
MessageBox.Show(typeof(TObject).ToString());
// If you want to instantiate:
GenericType = (TObject)Activator.CreateInstance(typeof(TObject));
}
}
UPDATE
As RupertMorrish noted, you can still compile the following code:
public class MyObj : IAllowedParamType
{
public int Id { get; set; }
public MyObj(int id)
{
Id = id;
}
}
And that should still rise an exception, because you just removed the implicit parameterless constructor. Of course, if you know what you are doing, this is hard to happen, however we can forbidden this by using new() on the 'where' type filtering - while also getting rid of the Activator.CreateInstance stuff.
The entire code:
// Maybe you should give a better name to this...
public interface IAllowedParamType { }
// Inherit all the possible classes with that
public class Parent : IAllowedParamType
{
string Name { get; set; }
bool HasChildren { get; set; }
int Age { get; set; }
}
public class Child : IAllowedParamType
{
string Name { get; set; }
int Age { get; set; }
}
// Filter the interface on the 'where'
public class DataController<TObject> where TObject : new(), IAllowedParamType
{
protected DbContext _context;
public DataController(DbContext context)
{
_context = context;
}
}
public class FormController<TObject> where TObject : new(), IAllowedParamType
{
private DataController<TObject> _dataController;
public FormController(Button btn, DataController<TObject> dataController)
{
_dataController = dataController;
btn.Click += new EventHandler(btnClick);
}
private void btnClick(object sender, EventArgs e)
{
GenericForm<TObject> form = new GenericForm<TObject>();
form.ShowDialog();
}
}
public class GenericForm<TObject> : Form where TObject : new(), IAllowedParamType
{
public TObject GenericType { get; set; }
public GenericForm()
{
Paint += GenericForm_Paint;
}
private void GenericForm_Paint(object sender, EventArgs e)
{
MessageBox.Show(typeof(TObject).ToString());
// If you want to instantiate:
GenericType = new TObject();
}
}
I think you can add a new type argument to FormController:
public class FormController<TParent, TChild>
where TParent : class
where TChild : class
{
...
public void showSubForm(string className)
{
IFormInterface f2 = new FormInterface<TChild>();
f2.ShowDialog();
}
}
So as I understand it, you want a Form<T> to open upon some action in the MainForm, with your MainForm using a FormController, as a manager of all your forms, relaying the generic type information to your Form<T>. Furthermore, the instantiated object of your Form<T> class should request an instance of a DatabaseController<T> class from your FormController.
If that is the case, the following attempt might work:
MainForm receives a reference to the FormController instance upon constructor initialization or has another way to interact with the FormController, e.g. a CommonService of which both know, etc.
This allows MainForm to call a generic method of the FormController to create and show a new Form object:
void FormController.CreateForm<T> ()
{
Form<T> form = new Form<T>();
form.Show();
// Set potential Controller states if not stateless
// Register forms, etc.
}
with Form<T> along the lines of:
class Form<T> : Form where T : class
{
DatabaseController<T> _dbController;
Form(FormController formController)
{
_dbController = formController.CreateDatabaseController<T>();
}
}
Now you have a couple of ways for the Form to receive a DatabaseController instance:
1. Your Form<T> receives a reference of the FormController or has another way to communicate with it to call a method along the lines of:
DatabaseController<T> FormController.CreateDatabaseController<T> ()
{
return new DatabaseController<T>();
}
Your FormController does not need to be generic, otherwise you'd need a new FormController instance for every T there is. It just needs to supply a generic method.
Your Form<T> receives an instance of the DatabaseController from the FormController upon constructor initialization:
void FormController.CreateForm ()
{
Form form = new Form(new DatabaseController());
form.Show();
}
with Form<T> being:
class Form<T> : Form where T : class
{
DatabaseController<T> _dbController;
Form(DatabaseController<T> controller)
{
_dbController = controller;
}
}
3. Like with 2 but your Form<T> and DatabaseController<T> provide static FactoryMethods to stay true to the Single Responsibility Priciple. e.g.:
public class Form<T> : Form where T : class
{
private DatabaseController<T> _dbController;
public static Form<T> Create<T>(DatabaseController<T> controller)
{
return new Form<T>(controller);
}
private Form(DatabaseController<T> controller)
{
_dbController = controller;
}
}
4. You can also use an IoC Container to register and receive instances of a specific type at runtime. Every Form<T> receives an instance of the IoC Container at runtime and requests its corresponding DatabaseController<T>. This allows you to better manage the lifetime of your controller and form objects within the application.
Well i'm not gonna go into the details here and will only suffice to some blueprints.
In this scenario i'd use a combination of Unity constructor injection with a generic factory to handle the instantiation given the type in main form.
It's not that intricate, take a look at Unity documentation at
Dependency Injection with Unity
The reason for picking Unity out of all DI containers is it was part of Enterprise Library from Microsoft itself and now continues to live on as an independent library in the form of Nugget. a friend of mine has recently ported Unity to .Net core, too. Simply put, it's hands down the most elaborate container available.
As for the factory i believe it's necessary because you don't wanna create a concrete lookup for handling all possible types, so it clearly has to be a generic factory. I'd advise you to make your factory a singleton and put it in whole another project, thereby separating your UI project from the models and both party will communicate through this DI bridge. you can even take a step further and process your model types using assembly reflection.
sorry for being too general, but i really don't know how familiar are you with these patterns. It really worth taking some time and utilizing these patterns. in my humble opinion there is no escape from these maneuvers if you want a truly scalable software.
You can reach me in private if you're looking for hints on implementation of any of the above-mentioned strategies.
Try Factory method.
public interface IProvider
{
T GetObject<T>();
}
Top-level form:
public class TopLevelForm : Form
{
public TopLevelForm(IProvider provider):base()
{
_provider = provider;
}
private void ShowSecondForm()
{
var f2 = new SecondForm(provider);
f2.Show();
}
}
Second-level form:
public class SecondLevelForm : Form
{
public SecondLevelForm(IProvider provider):base()
{
_data = provider.GetObject<MyEntity>();
}
}
As for IProvider's implementation - there are plenty of methods, starting from the simpliest one, return new T();

Attribute to mark as "internal use"

I made a class which requires the public default constructor but
that is never called; instead another constructor is used at DataGrid.AddingNewItem.
I'd like to tell developers that the default constructor is not for their use.
Is there an attribute which suits the purpose?
I had checked DebuggerNonUserCode and MethodImplAttribute with MethodImplAttributes.InternalCall but not sure that's the proper approach.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.dataGrid1.CanUserAddRows = true;
var list = new List<RowX>();
this.dataGrid1.ItemsSource = CollectionViewSource.GetDefaultView(list);
this.dataGrid1.AddingNewItem += (s, e) => e.NewItem = new RowX("ABC");
}
}
public class RowX
{
public RowX()
{
//this is not used. but CollectionView require this to be public or
//CanUserAddRows doesn't work.
}
public RowX(object o)
{
//this is the actual ctor.
}
public string Text { get; set; }
}
Mark it private
class Foo
{
private Foo() {}
}
You can give your constructor an access modifier.
private This means it can only be called from another constructor in that class.
public class PrivateClass
{
//Only from inside this class:
private PrivateClass()
{
}
public static PrivateClass GetPrivateClass()
{
//This calls the private constructor so you can control exactly what happens
return new PrivateClass();
}
}
internal This means only code in the same assembly (i.e. from inside your library) can access it.
public class InternalClass
{
//Only from within the same assembly
internal InternalClass(string foo)
{
}
}

How to initialize a static property before initializing a static class?

Below Class2 has a property that needs to be set before GetSomething is called, however because I access Class2 at the top of Class1 the property is always null when it gets to Something class. I can't seem to figure out how to change my code to set the property before it's used. Anyone?
EDIT
I want to pass the dependency from form1's constructor, not hardcode it further up the chain.
public partial class form1
{
private static readonly ISomeConstructedClass someConstructedClass = Class1.SomeConstructedClass;
public form1()
{
someConstructedClass.SomeDependency = new SomeDependency();
someConstructedClass.Whatever();
}
}
public static class Class1
{
public static readonly ISomething something = (ISomething)Class2.GetSomething("something");
public static ISomeConstructedClass SomeConstructedClass
{
get
{
return something.SomeConstructedClass;
}
}
}
....
}
public class Class2
{
public static ISomeDependency SomeDependency
{
get;
set;
}
public static GetSomething(string something)
{
switch(something)
{
case "something":
return new Something( SomeDependency );
}
}
}
public class Something : ISomething
{
public ISomeDependency SomeDependency
{
get;
set;
}
public Something(ISomeDependency someDependency)
{
SomeDependency = someDependency;
}
}
[Re]Edit:
I was confused about what you were trying to do before, you just need to create the dependency first.
public partial class form1
{
private static /*readonly*/ ISomeConstructedClass someConstructedClass;
public form1()
{
Class2.SomeDependency = new SomeDependency();
someConstructedClass = Class1.SomeConstructedClass;
someConstructedClass.Whatever();
}
}
I would also move the creation of something into the property just to make sure it is not initialized too soon (before the form1 constructor is called).
public static class Class1
{
public static ISomething something;
public static ISomeConstructedClass SomeConstructedClass
{
get
{
if (something == null) {
something = (ISomething)Class2.GetSomething("something");
}
return something.SomeConstructedClass;
}
}
}
You can use a static constructor. This is called before any static (or instance for that matter) fields or methods are called/accessed.
Something like:
static Class2() {
SomeDependency = SomeDependencyYouNeed;
}
Why are you using static methods? It looks like you're attempting a sort of Dependency Injection. Either create an instance of Class2 and pass the dependency in the constructor (and don't use static methods), or pass the dependency as a parameter of the GetSomething() method.
public static GetSomething(string something, ISomeDependency dependency).

How can I make one class solely responsible for creating and providing access to another class

This is how I understand I can implement the singleton pattern in C#:
public class ChesneyHawkes{
private static ChesneyHawkes _instance = new ChesneyHawkes();
public ChesneyHawkes Instance {get{return _instance;}}
private ChesneyHawkes()
{
}
}
What if I want to provide a single instance of an object, so that there can only ever be one, make the access to it public, but only allow it to be created or replaced by another singleton.
// The PuppetMaster should be the only class that
// can create the only existing Puppet instance.
public class PuppetMaster{
private static PuppetMaster_instance = new PuppetMaster();
public static PuppetMaster Instance {get{return _instance;}}
// Like a singleton but can be replaced at the whim of PuppetMaster.Instance
public static Puppet PuppetInstance {get {return Puppet;}}
private PuppetMaster()
{
}
public class Puppet{
// Please excuse the pseudo-access-modifier
puppetmasteronly Puppet(){
}
}
}
// To be accessed like so.
PuppetMaster.Puppet puppet = PuppetMaster.Instance.PuppetInstance;
You don't really need more than one singleton for that. Look at this example:
using System;
// interface for the "inner singleton"
interface IPuppet {
void DoSomething();
}
class MasterOfPuppets {
// private class: only MasterOfPuppets can create
private class PuppetImpl : IPuppet {
public void DoSomething() {
}
}
static MasterOfPuppets _instance = new MasterOfPuppets();
public static MasterOfPuppets Instance {
get { return _instance; }
}
// private set accessor: only MasterOfPuppets can replace instance
public IPuppet Puppet {
get;
private set;
}
}
class Program {
public static void Main(params string[] args) {
// access singleton and then inner instance
MasterOfPuppets.Instance.Puppet.DoSomething();
}
}

Categories

Resources