0

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?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
ArtK
  • 1,157
  • 5
  • 17
  • 31

6 Answers6

2

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'
    }
}
StevieB
  • 982
  • 7
  • 15
1

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.

Iain
  • 2,500
  • 1
  • 20
  • 24
  • As more explanation for why you don't need `ref`: `FormA` is a class, which means it will be passed `by reference`. You really only need `ref` for structures. – gunr2171 Dec 05 '13 at 04:49
  • 2
    When someone says... um I'd like to open this can, do you have a gun I can open this can with? You say, you need a can opener, not a gun, here's a can opener. You don't go... "here's your gun" – Mick Dec 05 '13 at 04:54
  • Thanks for your reply. Very useful second part. – ArtK Dec 05 '13 at 04:56
  • The problem with your answer is that getting the object name is easy. I need to get the instance name so I could access properties of the particular instance of an object. – ArtK Dec 05 '13 at 04:59
  • @user2611947 You don't need the instance name if you're using reflection. You pass the instance in. – Simon Whitehead Dec 05 '13 at 04:59
  • As Mick and I BOTH said in our answers... FormA already has an instance of FormB because it created it. If you have public properties in FormB, then FormA can read them at any time. And as Shravan said, you can create a delegate in FormB and handle the event in FormA if you really need to read the properties at specific times instead of simply on a dialogresult. – ohiodoug Dec 05 '13 at 05:02
1

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?

Community
  • 1
  • 1
  • This is one way I was looking at it but I still would need to know the name of an instance to pass a delegate. That is why I was thinking about FormHandler class to handle events and pass methods via delegates. – ArtK Dec 05 '13 at 05:05
  • When FormA's children creates FormB, you can assing a method in FormA to a delegate that lives in FormB. Call that method when FormB is done before you close FormB. The method can have a payload that is a datatype class to pass back the information. – Shravan Sunder Dec 05 '13 at 05:45
0

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.

ohiodoug
  • 1,493
  • 1
  • 9
  • 12
  • That goes without saying. You can instantiate FormB anywhere you want. But if FormB takes a string in its TextBox1 and you want to display that string in Label1 of the FormA's instance that called it (FormB) how would you do it? – ArtK Dec 05 '13 at 05:01
  • You can wrap a public property around the TextBox from FormB and expose it, or you can create a delegate and call the event from FormB when the TextBox value changes. If FormA is handling the event, then you can update the label in FormA. – ohiodoug Dec 05 '13 at 05:05
0

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...

Mick
  • 6,527
  • 4
  • 52
  • 67
0

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.

ArtK
  • 1,157
  • 5
  • 17
  • 31