tags:

views:

427

answers:

1

I've been using the factory model to create child forms to add to a MDI form. This is the code I've been using:

    /// <summary>
    /// This uses the Factory Model to create the child node and then add it to the MDI Parent (this)
    /// </summary>
    /// <param name="childName">String class name of the child, i.e. RentalEase.PropertyGrid must extend Form or SingleInstance</param>
    /// <param name="singleInstance">bool If this class is to be a single instance and restricted to only on instance. Must extend SingleInstance</param>
    public void createChild(string childName, bool singleInstance) {
        if (singleInstance) {
            try {
                BaseAndSingleInstanceForm f = BaseAndSingleInstanceForm.getInstanceByType(this, Type.GetType(childName));
                    f.MdiParent = this;
                    f.Show();
                    f.BringToFront();
                    this.Refresh();
            } catch (Exception ex) {
                MessageBox.Show("Could not create child: " + ex.ToString());
            }
        } else {
            try {
                object o = Activator.CreateInstance(Type.GetType(childName));
                if (o is Form) {
                    Form f = (Form)o;
                    f.MdiParent = this;
                    f.Show();
                    f.BringToFront();
                    this.Refresh();
                } else {
                    throw new ArgumentException("Invalid Class");
                }
            } catch (Exception ex) {
                MessageBox.Show("Could not create child: " + ex.ToString());
            }
        }
    }

However, a situation has arose that I have to add an integer parameter to the constructor of a specific form. How can I change this and make it reflect it while still maintaining the pattern at it's current ease of use (or nearly).

+5  A: 

You could add a Object[] parameter to the method that would represent the parameters to the constructor of the object you wish to instantiate. Then when you call Activator.CreateInstance you could pass that array in and Activator would do its best to find a constructor on the type you specified that matches the types in the Object array.

Here is a much simplified example of what I mean:

using System;

class Program
{
    static void Main()
    {
     Foo foo = (Foo)create("Foo", new Object[] { });
     Bar bar = (Bar)create("Bar", new Object[] { "hello bar" });
     Baz baz = (Baz)create("Baz", new Object[] { 2, "hello baz" });
    }

    static Object create(String typeName, Object[] parameters)
    {
     return Activator.CreateInstance(Type.GetType(typeName), parameters);
    } 
}

class Foo
{
    public Foo() { }
}

class Bar
{
    public Bar(String param1) { }
}

class Baz
{
    public Baz(Int32 param1, String param2) { }
}

We have three types that all have different constructors - if the caller is responsible for sending in the type name then they will also be responsible for supplying an array of Objects that will satisfy a non-default constructor.

Andrew Hare