get object's instance name at runtime - c#

I need to get a name of object's instance at runtime. I have a way of doing it but I think there must be a better way.
Let's say I have 4 forms: FormA1, FormA2, FormA2 and DormA4. They all derive from FormA. FormA never gets instantiated - let's say it is virtual.
I also have FormB. Each of the FormA children can at runtime, upon certain event, instantiate FormB. FormB's job is to take some information and return it to the form that called it (instantiated it) at runtime. But without knowing the name of calling form's instance I can't access any of calling form's properties.
The way I currently do it is I have a constructor in FormB that takes a reference to sender as argument using FormA as type, example:
public class FormB : Form
{
private FormA referenceForm;
public FormB(ref FormA callingForm)
{
referenceForm = callingForm;
}
}
this way I can hale local methods access properties of calling form. Of course to get specific properties I need code reflection so I would get the right type and access to specific properties of children.
Alternatively, I think, I could create FormHandler class, instantiate it every time child form gets instantiated and pass values inside events but this may make it more complicated than necessary.
So the question is, how do you get instance name of an object so you can access its properties?

You haven't explained why and when you need to do this but it sounds like you're looking for the publisher-subscribed pattern. You can use delegates/events for this e.g here FormB publishes interesting events to FormA
public class InterstingInfo
{
// TODO
}
public class FormB
{
public delegate void Callback(InterstingInfo interestingData);
public event Callback observer;
private void NotifyObserver()
{
InterstingInfo interstingInfo = null;
// TODO setup intersting data
observer.Invoke(interstingInfo);
}
}
public class FormA
{
void CreateFormB()
{
FormB formB = new FormB();
formB.observer += (o) => { DoStuffForOtherForm(o); };
}
void DoStuffForOtherForm(InterstingInfo interestingData)
{
// TODO - Do stuff based on 'interstingInfo'
}
}

Is this what you want?
obj.GetType().Name
This will tell you the name (e.g. FormA1)
As an aside, there is no need to use ref in your constructor.

This isn't a direct answer to your question. But you should be using a delegate system. Setup a delegate in FormB that the instantiator of FormB can assign an action to. You can pass the required parameters through the delegate.
See this for more info: https://stackoverflow.com/a/639366/2696641
Where do I use delegates?

FormB should be able to be instantiated anywhere and ideally not care or know about who created it. A better approach for you would be to expose whatever properties you need available in FormB and let the calling object read them.

Well...
I think you're asking for a specific answer. When you should be asking a general... how should I do this.
I would expose all the data your FormAs need from the FormB as properties on FormB. Then I would expose an event on FormB so that FormA knows when to populate itself from B.
http://msdn.microsoft.com/en-us/library/ak9w5846.aspx
This is basically the GOF Observer pattern...

I guess in the end I could just instantiate each of the FormAs to the same name at the runtime, regardless of the form and refer to that arbitrary single name. That as long as I do not instantiate FormAs concurrently.

Related

Callback vs object reference

Design question: Suppose we have parent and child object. Sometimes child object says "Parent, you've got to update your state." So, is there any critical difference between
Passing parent object reference into child contructor
and
Passing parent object callBack function into child constructor
of course, Except the case when child has to be revoked any chance to affect parent object other than using this callBack function.
Seems like a good case for the observer pattern especially if the child doesn't really need any state information from the parent. And if the parent wants to ignore the child (sadly happens so often) you can simply unsubscribe from the event.
class Parent
{
public Parent(Child child)
{
Child = child;
Child.UpdateYourStatus += ComputeNewStateAndOutput;
}
Child Child {get; set;}
private void ComputeNewStateAndOutput(sender, e) { ... }
public void DisownChild()
{
//You are no longer my son (sigh, heard that one before)
Child.UpdateYourStatus -= ComputeNewStateAndOutput;
}
}
class Child
{
public event EventHandler UpdateYourStatus;
}
Your two choices are basically the same thing underneath, so you could feel free to choose your own preferred flavour of syntactic sugar. In both cases there's a callback function signature defined in some type (a class or interface in the first case, a delegate type in the second case) and an object reference (passed in explicitly in the first case, or bound up in a delegate instance in the second case).
Microsoft do have some guidelines on when you might want to choose one over another: https://msdn.microsoft.com/library/2e759bdf-7ca4-4005-8597-af92edf6d8f0
One good reason to choose an object reference/interface over a callback is that you know you are definitely going to invoke multiple callbacks on the parent. It makes sense to pass in a single reference implementing an interface that defines all those callbacks, rather than having to create a bunch of delegate instances and pass them all in together.
Conversely, if you know you're going to want multiple different implementations of the callback for a single object, eg. because yo uwant to respond in quite different ways to the callback being invoked by different children, it might make more sense to use function pointers/delegates, but in either case you're not forced to choose one option over the other.

C# User Control Dependency Injection [duplicate]

Call me crazy, but I'm the type of guy that likes constructors with parameters (if needed), as opposed to a constructor with no parameters followed by setting properties. My thought process: if the properties are required to actually construct the object, they should go in the constructor. I get two advantages:
I know that when an object is constructed (without error/exception), my object is good.
It helps avoid forgetting to set a certain property.
This mindset is starting to hurt me in regards to form/usercontrol development. Imagine this UserControl:
public partial class MyUserControl : UserControl
{
public MyUserControl(int parm1, string parm2)
{
// We'll do something with the parms, I promise
InitializeComponent();
}
}
At designtime, if I drop this UserControl on a form, I get an Exception:
Failed to create component 'MyUserControl' ...
System.MissingMethodException - No parameterless constructor defined for this object.
It seems like, to me, the only way around that was to add the default constructor (unless someone else knows a way).
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
}
public MyUserControl(int parm1, string parm2)
{
// We'll do something with the parms, I promise
InitializeComponent();
}
}
The whole point of not including the parameterless constructor was to avoid using it. And I can't even use the DesignMode property to do something like:
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
if (this.DesignMode)
{
InitializeComponent();
return;
}
throw new Exception("Use constructor with parameters");
}
}
This doesn't work either:
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
Fine, moving along ...
I have my parameterless constructor, I can drop it on the form, and the form's InitializeComponent will look like this:
private void InitializeComponent()
{
this.myControl1 = new MyControl();
// blah, blah
}
And trust me, because I did it (yes, ignoring the comments Visual Studio generated), I tried messing around and I passed parameters to InitializeComponent so that I could pass them to the constructor of MyControl.
Which leads me to this:
public MyForm()
{
InitializeComponent(); // Constructed once with no parameters
// Constructed a second time, what I really want
this.myControl1 = new MyControl(anInt, aString);
}
For me to use a UserControl with parameters to the constructor, I have to add a second constructor that I don't need? And instantiate the control twice?
I feel like I must be doing something wrong. Thoughts? Opinions? Assurance (hopefully)?
Design decisions made regarding the way Windows Forms works more or less preclude parameterized .ctors for windows forms components. You can use them, but when you do you're stepping outside the generally approved mechanisms. Rather, Windows Forms prefers initialization of values via properties. This is a valid design technique, if not widely used.
This has some benefits, though.
Ease of use for clients. Client code doesn't need to track down a bunch of data, it can immediately create something and just see it with sensible (if uninteresting) results.
Ease of use for the designer. Designer code is clearer and easier to parse in general.
Discourages unusual data dependencies within a single component. (Though even microsoft blew this one with the SplitContainer)
There's a lot of support in forms for working properly with the designer in this technique also. Things like DefaultValueAttribute, DesignerSerializationVisibilityAttribute, and BrowsableAttribute give you the opportunity to provide a rich client experience with minimal effort.
(This isn't the only compromise that was made for client experience in windows forms. Abstract base class components can get hairy too.)
I'd suggest sticking with a parameterless constructor and working within the windows forms design principles. If there are real preconditions that your UserControl must enforce, encapsulate them in another class and then assign an instance of that class to your control via a property. This will give a bit better separation of concern as well.
There are two competing paradigms for designing classes:
Use parameterless constructors and set a bunch of properties afterwards
Use parameterized constructors to set properties in the constructor
The Visual Studio Windows Forms Designer forces you to provide a parameterless constuctor on controls in order to work properly. Actually, it only requires a parameterless constructor in order to instantiate controls, but not to design them (the designer will actually parse the InitializeComponent method while designing a control). This means that you can use the designer to design a form or user control without a parameterless constructor, but you cannot design another control to use that control because the designer will fail to instantiate it.
If you don't intend to programmatically instantiate your controls (i.e. build your UI "by hand"), then don't worry about creating parameterized constructors, since they won't be used. Even if you are going to programmatically instantiate your controls, you may want to provide a parameterless constructor so they can still be used in the designer if need be.
Regardless of which paradigm you use, it is also generally a good idea to put lengthy initialization code in the OnLoad() method, especially since the DesignMode property will work at load time, but not work in the constructor.
I would recommend
public partial class MyUserControl : UserControl
{
private int _parm1;
private string _parm2;
private MyUserControl()
{
InitializeComponent();
}
public MyUserControl(int parm1, string parm2) : this()
{
_parm1 = parm1;
_parm2 = parm2;
}
}
As this way the base constructor is always called first and any references to components are valid.
You could then overload the public ctor if need be, ensuring the control is always instantiated with the correct values.
Either way, you ensure that the parameterless ctor is never called.
I haven't tested this so if it falls over I apologise!
This is unfortunately a design issue that will occur frequently, not just in the control space.
There are often situations where you need to have a parameterless constructor, even though a parameterless constructor is not ideal. For example, many value types, IMO, would be better off without parameterless constructors, but it's impossible to create one that works that way.
In these situations, you have to just design the control/component in the best manner possible. Using reasonable (and preferably the most common) default parameters can help dramatically, since you can at least (hopefully) initialize the component with a good value.
Also, try to design the component in a way that you can change these properties after the component is generated. With Windows Forms components, this is typically fine, since you can pretty much do anything until load time safely.
Again, I agree - this isn't ideal, but it's just something we have to live with and work around.
Well, in short, the designer is the kind of guy that likes parameter-less constructors. So, to the best of my knowledge, if you really want to use parameter based constructors you are probably stuck with working around it one way or the other.
Just do this:
public partial class MyUserControl : UserControl
{
public MyUserControl() : this(-1, string.Empty)
{
}
public MyUserControl(int parm1, string parm2)
{
// We'll do something with the parms, I promise
if (parm1 == -1) { ... }
InitializeComponent();
}
}
Then the 'real' constructor can act accordingly.
Provide a parameterless constructor for the designer and make it private - if you really must do it this way... :-)
EDIT: Well of course this won't work for UserControls. I obviously wasn't thinking clearly. The designer need to execute the code in InitializeComponent() and it's can't work if the constructor is private. Sorry about that. It does work for forms, however.
It's quite a while since the question was asked, but maybe my approach is helpful to somebody.
I personally also prefer to use parameterized Constructors to avoid forgetting to set a certain property.
So instead of using the actual Constructor I simply define a public void PostConstructor where all things are put you would normally put in the Constructor. So the Actual Constructor of the UserControl always contains only InitializeComponent().
This way you don't have to adjust your favourite programming paradigm to VisualStudios needs to run the Designer properly. For this programming schema to work it has to be followed from the very bottom.
In practice this PostConstructionalizm would look somewhat like this:
Let's start with a Control at the bottom of your UserControl call hierarchy.
public partial class ChildControl : UserControl
{
public ChildControl()
{
InitializeComponent();
}
public void PostConstructor(YourParameters[])
{
//setting parameters/fillingdata into form
}
}
So a UserControl containing the ChildControl would look something like that:
public partial class FatherControl : UserControl
{
public FatherControl()
{
InitializeComponent();
}
public void PostConstructor(YourParameters[])
{
ChildControl.PostConstructor(YourParameters[])
//setting parameters/fillingdata into form
}
}
And finally a Form calling one of the User Control simply puts the PostConstructor after InitializeComponent.
public partial class UI : Form
{
public UI(yourParameters[])
{
InitializeComponent();
FatherControl.PostConstructor(yourParameters[]);
}
}
I have a way to work around it.
Create a control A on the form with the parameterless constructor.
Create a control B with parameterized constructor in the form contstructor.
Copy position and size from A to B.
Make A invisible.
Add B to A's parent.
Hope this will help. I just encountered the same question and tried and tested this method.
Code for demonstrate:
public Form1()
{
InitializeComponent();
var holder = PositionHolderAlgorithmComboBox;
holder.Visible = false;
fixedKAlgorithmComboBox = new MiCluster.UI.Controls.AlgorithmComboBox(c => c.CanFixK);
fixedKAlgorithmComboBox.Name = "fixedKAlgorithmComboBox";
fixedKAlgorithmComboBox.Location = holder.Location;
fixedKAlgorithmComboBox.Size = new System.Drawing.Size(holder.Width, holder.Height);
holder.Parent.Controls.Add(fixedKAlgorithmComboBox);
}
holder is Control A, fixedKAlgorithmComboBox is Control B.
An even better and complete solution would be to use reflect to copy the properties one by one from A to B. For the time being, I am busy and I am not doing this. Maybe in the future I will come back with the code. But it is not that hard and I believe you can do it yourself.
I had a similar problem trying to pass an object created in the main Windows Form to a custom UserControl form. What worked for me was adding a property with a default value to the UserControl.Designer.cs and updating it after the InitializeComponent() call in the main form. Having a default value prevents WinForms designer from throwing an "Object reference not set to an instance of an object" error.
Example:
// MainForm.cs
public partial class MainForm : Form
public MainForm()
{
/* code for parsing configuration parameters which producs in <myObj> myConfig */
InitializeComponent();
myUserControl1.config = myConfig; // set the config property to myConfig object
}
//myUserControl.Designer.cs
partial class myUserControl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
// define the public property to hold the config and give it a default value
private myObj _config = new myObj(param1, param2, ...);
public myObj config
{
get
{
return _config ;
}
set
{
_config = value;
}
}
#region Component Designer generated code
...
}
Hope this helps!

How to know the derived class in the base class

I've searched everywhere on this and can't find anyone doing anything similar. I'm quite a newbie at C# having worked 15 years with a non-object orientated language, so I hope I'm not missing something simple.
I am trying to make a standard Winform which get's inherited, so that I don't need to repeat the code I use every time (one of the joys of .Net over what I've used for years is the ability to centralize things far more).
My problem comes that I want to implement the ability to either call the derived classes as 'single instance' or 'multiple instance' when launched from the MDI and after much much searching I've almost achieved this using 'generics'. But I've got stuck with how to know which class the current form is, to pass that to the generic class to close the form.
A simplified version of my code will help understand my problem. This is my generic class designed for launching and closing the form. It determines if the Instance for T already exists, depending on if you are launching a single or multiple instance it either shows that, or creates a new instance of the form. The MDI for is passed in the launch methods to allow me to attach the new form to that.
public class FormLaunch<T> where T : MyBaseForm, new()
{
public static T Instance;
public static void LaunchultipleInstnace(FRMMDI mdi)
{
Instance = new T();
Instance.MdiParent = mdi;
Instance.Show();
Instance.BringToFront();
}
public static void LaunchSingleInstance(FRMMDI mdi)
{
if (Instance == null) Instance = new T();
Instance.MdiParent = mdi;
Instance.Show();
Instance.BringToFront();
}
public static void CloseInstance()
{
Instance = null;
}
}
A 'Single Instance' version of the form is launched from the MDI using the following statement.
FormLaunch<MyDerivedClass>.LaunchSingleInstance(this);
The problem comes that I would like to handle the closing of the form once in my base form and not have to do it every time in the derived forms. But I can't work out how to do this.
public partial class MyBaseForm : Form
{
public MyBaseForm()
{
InitializeComponent();
}
private void MyBaseForm_FormClosed(object sender, FormClosedEventArgs e)
{
FormLaunch<this.GetType()>.CloseInstance();
}
}
But this.GetType() does not work. If I was just using this form directly rather than inheriting it I could just use
FormLaunch<MyBaseForm>.CloseInstance();
Or if I handled the FormClosed event in every derived class then I could just use
FormLaunch<MyDerivedClass>.CloseInstance();
But I really want to do this in a way that stops me forgetting to do this every time in the derived class... because I wrote this a few months ago and have already forgotten pretty much every time I've used it.
EDIT: My question is really, what do I pass in the place of T in
FormLaunch<T>.CloseInstance()
This needs to refer to the derived class and I can't seem to find that. this.GetType() refers to the correct glass but does not work.
If what you want is just to enuse the single instance of the Form is opened you can read the answer of Jon Skeet to this question
And just a pair of another points.
You mix different things: .NET generics and inheritance.
this.GetType() returns an instance of System.Type class, describing the current instance class (this),
Type parameter in GenericClass<TypeParameter> is just a name of the concrete class in using, or a type parameter name in the generic class definition: Generic<TParam>
you can't define generic Control or Form classes. The Designer is not capable to serialize them.
You can simply subscribe to FormClosed in LaunchSingleInstance() and remove handling of close event from form itself completely:
public static void LaunchSingleInstance(FRMMDI mdi)
{
if (Instance == null)
{
Instance = new T();
Instance.FormClosed += (s, e) => CloseInstance();
}
Instance.MdiParent = mdi;
Instance.Show();
Instance.BringToFront();
}
A more direct answer - it is possible using reflection:
typeof(FormLaunch<>).MakeGenericType(this.GetType())
.GetMethod("CloseInstance")
.Invoke(null, null);

Is it okay to refer to "this" in the constructor?

In C#, a common pattern that I use is to populate the details of a lower calculation class with a form object.
The constructor for MyForm is:
MyForm()
{
_MyFormCalcs = new MyFormCalcs(this);
}
But I encountered an error today which makes me think that as my constructor had not finished completing, it creates a new instance of MyForm to pass into MyData. Thus it calls the constructor twice. I found that a static list in MyFormCalcs was being filled twice and was failing the second time as the keys were already present in the list.
Can I use this in the constructor to refer to this instance? What will it contain in the lower class - has the constructor been run or not.
What is a better way of passing my form into the lower class?
No, that won't create a new instance of MyForm.
In general, allowing this to "escape" from a constructor is dangerous as it means it can be used before the constructor has completed, but it's not going to be creating a new instance. If you could give a short but complete example of the problem you've seen, we could help diagnose it further. In particular, it's not clear what you mean about the "static list being filled twice". Usually it's not a good idea to populate a static variable in an instance constructor.
In fact, it is really nice to avoid such call inside constructor, because your object is not already built (constructor hasnt finish its work) but you are already use this "unfinished" object as a parameter. Its a bad way. Good way is creating some special method:
class MyClass
{
var obj:SomeClass;
public MyClass()
{
}
public Init()
{
obj = SomeClass(this);
}
}
Make a private property that instantiate MyFormCalcs only when it is first used, like this:
public class MyForm {
private MyFormCalcs MyFormCalcs {
get {
_MyFormCalcs = _MyFormCalcs ?? new MyFormCalcs(this);
}
}
}
This way, you don't have to think about when to "initialize" things.
There is this very complete response of C# constructor order:
C# constructor execution order

Passing form object by reference

Hey! I've made a little boiler system that's controlled entirely by a form. The form components, however, call functions in a class for the boiler, radiators and so on.
I've got a little main class to that instantiates all of the classes but I'm struggling to figure out how to pass the form object to those classes so that they can access the form's components.
I guess I should be using mutator methods in each class to store the form object? How would I do this that's syntactically correct?
Thank you! ;o)
Just pass the form to each class. Store it in a private variable so the class can use it later. It is passed by reference by default.
class Boiler {
private Form parentForm;
public Boiler(Form f) {
parentForm = f;
}
}
When you pass a reference type to a method, C# (by default) will pass a copy of the reference to the method. This means that if pass the reference you have to your classes you are giving the method a copy of that reference and since both copies reference the same object both the call site and the method will have access to the same instance.
For example:
class Example
{
static void Main()
{
string s = "hello, world";
// Here we are passing a copy of the reference
// stored in "s" to "Print"
Print(s);
}
static void Print(string str)
{
// By default, "str" will be assigned the copy of the
// reference passed to this method.
Console.WriteLine(s);
}
}
I would be careful building an application in which your domain objects (in your case, Boiler, Radiator, etc.) know about the UI layer that consumes them. If you find that you need to pass a Form to one of these domain models you are probably doing something wrong. If you show us a small example of what you are trying to accomplish we might be able to help you come up with a more maintainable solution.

Categories

Resources