Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Generic parameter/reflection problem

Generic parameter/reflection problem

Scheduled Pinned Locked Moved C#
helptutorialquestion
13 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Pete OHanlon

    This behaviour is because you are trying to use a variable instead of a type. This goes against the nature of generics which identifies information about an object at compile time. Now, to get around this you would use:

    GetForm<Form>("myformid");
    

    Please visit http://www.readytogiveup.com/ and do something special today. Deja View - the feeling that you've seen this post before.

    B Offline
    B Offline
    Bekjong
    wrote on last edited by
    #4

    I know how to get around it. The thing is, I want to provide the type at runtime using reflection. The reason for this is that somewhere in the GetForm method there's a line saying: formType ret = Activator.CreateInstance(); I need to call the specific constructor for the type that's provided. This is why simply passing type Form will not do. Since I can ensure the compiler that the type passed will be a descendant of Form, I figured there's enough information for it to work with.

    Standards are great! Everybody should have one!

    P 1 Reply Last reply
    0
    • C Chintan Desai

      Biggest mistake : this code : Type classToGet = typeof(Form); here Form is the base class of all the forms, so u cant use base class to get the type of form. Instead if u use as argument in typeof() any derived class of base class(Form)then it will return that derived Class and base on it this code : Type classToGet = typeof(DerivedClassOfForm);//Return Form "derived Class" which you can during debug time it will view as GetForm("myformId") GetForm("myformid"); This is difficult to explain as well as to understand :confused:.For more details learn Factory Pattern from http://www.c-sharpcorner.com.:rose:

      Regards Chintan www.visharadsoft.com (Nothing is so purify as KNOWLEDGE)

      B Offline
      B Offline
      Bekjong
      wrote on last edited by
      #5

      Actually it doesn't work with Form-derived classes either: The Form class was really just an example: At runtime it can be any class implementing Form. Thank you anyway, I'll try and see what I can find at c sharp corner too.

      Standards are great! Everybody should have one!

      L 1 Reply Last reply
      0
      • B Bekjong

        I know how to get around it. The thing is, I want to provide the type at runtime using reflection. The reason for this is that somewhere in the GetForm method there's a line saying: formType ret = Activator.CreateInstance(); I need to call the specific constructor for the type that's provided. This is why simply passing type Form will not do. Since I can ensure the compiler that the type passed will be a descendant of Form, I figured there's enough information for it to work with.

        Standards are great! Everybody should have one!

        P Offline
        P Offline
        Pete OHanlon
        wrote on last edited by
        #6

        I don't understand why you would want to do this in this way. As I stated before, generics are really handled at compile time. I knocked up the following quick routine to get a form.

        namespace GenericForms
        {
          public static class TestForms
          {
            public static Form ShowForm(string formName)
            {
              return (Form)Activator.CreateInstance(Type.GetType(formName));
            }
          }
        }
        

        Calling this becomes as simple as GenericForms.TestForms.ShowForm("Form1").ShowDialog();.

        Please visit http://www.readytogiveup.com/ and do something special today. Deja View - the feeling that you've seen this post before.

        B 1 Reply Last reply
        0
        • B Bekjong

          Actually it doesn't work with Form-derived classes either: The Form class was really just an example: At runtime it can be any class implementing Form. Thank you anyway, I'll try and see what I can find at c sharp corner too.

          Standards are great! Everybody should have one!

          L Offline
          L Offline
          Le centriste
          wrote on last edited by
          #7

          Generics are for compile-time type resolution. For run-time types, use abstract classes or interfaces.

          ----- If atheism is a religion, then not collecting stamps is a hobby. -- Unknown

          1 Reply Last reply
          0
          • P Pete OHanlon

            I don't understand why you would want to do this in this way. As I stated before, generics are really handled at compile time. I knocked up the following quick routine to get a form.

            namespace GenericForms
            {
              public static class TestForms
              {
                public static Form ShowForm(string formName)
                {
                  return (Form)Activator.CreateInstance(Type.GetType(formName));
                }
              }
            }
            

            Calling this becomes as simple as GenericForms.TestForms.ShowForm("Form1").ShowDialog();.

            Please visit http://www.readytogiveup.com/ and do something special today. Deja View - the feeling that you've seen this post before.

            B Offline
            B Offline
            Bekjong
            wrote on last edited by
            #8

            The thing is, I'm working in a MDI application and want to store and retrieve all of the forms that were open when the application last closed. Here's my code, maybe not so pretty, but I think you'll get it... using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Drawing; using System.Diagnostics; namespace Tools { [Serializable] public class FormsPool { /// /// This dictionary will store the form's properties that we want to save to file. /// private Dictionary dataPool = new Dictionary(); /// /// And this one is used to store forms at runtime. /// [field: NonSerialized] private Dictionary formPool = new Dictionary(); /// /// Get the form with the specified id. /// /// Unique string identifying the form to get. /// public Form GetForm(string form_id) { return GetForm

            (form_id); } /// /// Returns the form with the given id from the pool. If it's not there, it'll be constructed. /// /// The form class you want to be returned. /// The id for the form to return. /// public formType GetForm(string form_id) where formType : Form { if (formPool == null) // make sure our dictionaries are there formPool = new Dictionary(); // (deserialization can set them to be null) if (dataPool == null) dataPool = new Dictionary(); if (this.formPool.ContainsKey(form_id)) // check out if we have a reference to the form { if (formPool[form_id] != null) return formPool[form_id] as formType; // if so, return it else formPool.Remove(form_id); } formType ret = Activator.CreateInstance(); // not there, so create it if (dataPool.ContainsKey(form_id)) //

            1 Reply Last reply
            0
            • B Bekjong

              Hi, I've created the following function (it gets forms from a pool): public formType GetForm<formType>(string form_id) where formType : Form I've stored the type of form I want to get in a Type variable somewhere, for example: Type classToGet = typeof(Form); The Form is just an example, this normally determined dynamically. Now when I try to call my GetForm function like this: GetForm<classToGet>("myformid"); I get a compiler exception saying "classToGet is a type parameter but is used like variable" and that "Type or namespace classToGet could not be found". Is there anyway of solving this problem? I suppose there's a problem involving me not understanding reflection thoroughly enough. I realize I'm passing an argument of type Type but I can't seem te get my mind around converting the Type class to the class-reference I need here. Thanks in advance for any help!

              Standards are great! Everybody should have one!

              A Offline
              A Offline
              AFSEKI
              wrote on last edited by
              #9

              Dictionary pool = new Dictionary(10); pool.Add("myformid", new LoginForm()); pool.Add("myAboutformid", new AboutForm()); public class LoginForm : Form { } public class AboutForm : Form { } Type typLoginForm = typeof(LoginForm); LoginForm lf = GetForm("myformid"); lf.ShowDialog(); public T GetForm(string form_id) where T: Form { return pool[form_id] as T; } You can change the Dictionary to Dictionary> to add more than 1 item under the same key. Or Dictionary> to get a pool item with its type instead of form_id value which is string. Fire and Water, Love and Death, Sex and the City? :)

              B 1 Reply Last reply
              0
              • A AFSEKI

                Dictionary pool = new Dictionary(10); pool.Add("myformid", new LoginForm()); pool.Add("myAboutformid", new AboutForm()); public class LoginForm : Form { } public class AboutForm : Form { } Type typLoginForm = typeof(LoginForm); LoginForm lf = GetForm("myformid"); lf.ShowDialog(); public T GetForm(string form_id) where T: Form { return pool[form_id] as T; } You can change the Dictionary to Dictionary> to add more than 1 item under the same key. Or Dictionary> to get a pool item with its type instead of form_id value which is string. Fire and Water, Love and Death, Sex and the City? :)

                B Offline
                B Offline
                Bekjong
                wrote on last edited by
                #10

                Thanks. But this way I'll be creating a new Form eacht time the GetForm function is called, while all I really want is a reference to an existing instance of the form if it exists, or a reference to a new instance if it doesn't. This works. The real problem for me is that the pool is serializable: Some basic data (location, position) can be stored and retrieved from a file. I save the info when the application is exited. When I start it up I want it to reconstruct each instance using its respective constructor...

                Standards are great! Everybody should have one!

                A 1 Reply Last reply
                0
                • B Bekjong

                  Thanks. But this way I'll be creating a new Form eacht time the GetForm function is called, while all I really want is a reference to an existing instance of the form if it exists, or a reference to a new instance if it doesn't. This works. The real problem for me is that the pool is serializable: Some basic data (location, position) can be stored and retrieved from a file. I save the info when the application is exited. When I start it up I want it to reconstruct each instance using its respective constructor...

                  Standards are great! Everybody should have one!

                  A Offline
                  A Offline
                  AFSEKI
                  wrote on last edited by
                  #11

                  No, you won't be creating a new Form each time. It was just an example, you can replace: pool.Add("myformid", new LoginForm()); pool.Add("myAboutformid", new AboutForm()); as pool.Add("myformid", myAlreadyCreatedLoginForm); pool.Add("myAboutformid", myAlreadyCreatedAboutForm()); also: GetForm(...) code I sent you does not create anything. Do you see any "new" keyword in the code/or am I blind? Result: - You have an assembly created in you bin\debug folder in which your Forms are also embedded. This is your store to create the Forms at run-time. You want to store some configuration related to your forms, so what you need is to store this configuration like size and location somewhere like an xml file. If you've done it(you've written Some basic data(location, position) can be retrieved from a file), then you want to get a Form from the pool. Then your pool is the one which is responsible of returning an instance of the Form type if there is already one, created in pre-call to GetForm(...) or you want to create a new instance with the configuration parameters stored using reflection. If this is what you want: // The configurtation of the Form you serialize/deserialize public class FormConfig : ConfigurationProperty /*or string, or xml file, or whatever you want */ { } public T GetForm(string form_id) where T: Form { if(pool.ContainsKey(form_id)) { return pool[form_id] as T; } else { // you may have a look at other overloaded method(s) of Activator.CreateInstance return Activator.CreateInstance(T, new object[]{GetConfig(typeof(mySerializedForm))}) as T; } } public FormConfig GetConfig(string key) { return ..... // return the deserialized config } public FormConfig GetConfig(Type key) { return ..... // return the deserialized config } "Peace at home, peace in the world" Mustafa Kemal Atatürk(the founder of the Republic of Turkey and its first President.))

                  B 1 Reply Last reply
                  0
                  • A AFSEKI

                    No, you won't be creating a new Form each time. It was just an example, you can replace: pool.Add("myformid", new LoginForm()); pool.Add("myAboutformid", new AboutForm()); as pool.Add("myformid", myAlreadyCreatedLoginForm); pool.Add("myAboutformid", myAlreadyCreatedAboutForm()); also: GetForm(...) code I sent you does not create anything. Do you see any "new" keyword in the code/or am I blind? Result: - You have an assembly created in you bin\debug folder in which your Forms are also embedded. This is your store to create the Forms at run-time. You want to store some configuration related to your forms, so what you need is to store this configuration like size and location somewhere like an xml file. If you've done it(you've written Some basic data(location, position) can be retrieved from a file), then you want to get a Form from the pool. Then your pool is the one which is responsible of returning an instance of the Form type if there is already one, created in pre-call to GetForm(...) or you want to create a new instance with the configuration parameters stored using reflection. If this is what you want: // The configurtation of the Form you serialize/deserialize public class FormConfig : ConfigurationProperty /*or string, or xml file, or whatever you want */ { } public T GetForm(string form_id) where T: Form { if(pool.ContainsKey(form_id)) { return pool[form_id] as T; } else { // you may have a look at other overloaded method(s) of Activator.CreateInstance return Activator.CreateInstance(T, new object[]{GetConfig(typeof(mySerializedForm))}) as T; } } public FormConfig GetConfig(string key) { return ..... // return the deserialized config } public FormConfig GetConfig(Type key) { return ..... // return the deserialized config } "Peace at home, peace in the world" Mustafa Kemal Atatürk(the founder of the Republic of Turkey and its first President.))

                    B Offline
                    B Offline
                    Bekjong
                    wrote on last edited by
                    #12

                    Hmm, I think I might have been having a bit of an off day in explaining what I was aiming for, but you guessed about right the second time. This line of code was close enough to what I was looking for:

                    return Activator.CreateInstance(T, new object[]{GetConfig(typeof(mySerializedForm))}) as T;

                    I've just been staring at the same CreateInstance method without ever realizing there's a bunch of overloads to choose from. Thanks very much for the help :).

                    Standards are great! Everybody should have one!

                    A 1 Reply Last reply
                    0
                    • B Bekjong

                      Hmm, I think I might have been having a bit of an off day in explaining what I was aiming for, but you guessed about right the second time. This line of code was close enough to what I was looking for:

                      return Activator.CreateInstance(T, new object[]{GetConfig(typeof(mySerializedForm))}) as T;

                      I've just been staring at the same CreateInstance method without ever realizing there's a bunch of overloads to choose from. Thanks very much for the help :).

                      Standards are great! Everybody should have one!

                      A Offline
                      A Offline
                      AFSEKI
                      wrote on last edited by
                      #13

                      If I could help you then I'm glad to win a coder's heart :-D

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups