Beware my nasty code! - how can I simplify this?

Hi have the following switch statement that tests for a value and then loads up its relating Form.

switch (objQuestion.m_objQuestionType.m_strCustomForm)
{
case "FormInspectionAnswerCustomLocation":
frm = new FormInspectionAnswerCustomLocation(ref objQuestion);
break;
case "FormInspectionAnswerCustomCause":
frm = new FormInspectionAnswerCustomCause(ref objQuestion);
break;
case "FormInspectionAnswerCustomProduct":
frm = new FormInspectionAnswerCustomProduct(ref objQuestion);
break;
case "FormInspectionAnswerCustomSupplier":
frm = new FormInspectionAnswerCustomSupplier(ref objQuestion);
break;
case "FormInspectionAnswerCustomMeasurement":
frm = new FormInspectionAnswerCustomMeasurement(ref objQuestion);
break;
case "FormInspectionAnswerCustomWorkPackage":
frm = new FormInspectionAnswerCustomWorkPackage(ref objQuestion);
break;
}

But as the value being tested is the same as the Form that needs to be called, I was thinking that maybe there is a smarter way of doing this I've heard about Activator.CreateInstance, would this be of any use

Thanks



Answer this question

Beware my nasty code! - how can I simplify this?

  • Wilk06

    Yes you can using the following code:

    Type type = Type.GetType(objQuestion.m_objQuestionType.m_strCustomForm);
    object obj = Activator.CreateInstance(type, objQuestion);

    There are three issues however.

    1) The type name passed to GetType must be fully qualified with the namespace otherwise it'll fail.

    2) You require a reference parameter but what will get passed through CreateInstance won't be a reference parameter. Therefore any changes you make will not be seen. You shouldn' probably be passing by ref anyway since it is an object.

    3) The returned value is an object so you'll need to be able to cast the returned value to some more meaningful type that you can use such as a form or something.

    You can wrap the above code in a nice generic method as well:

    static
    T CreateObject<T> ( string typeName, params object[] args )
    {
    Type type = Type.GetType(typeName);
    return (T)Activator.CreateInstance(type, args);
    }

    If you restrict T to being a class then you can use the as operator.

    Michael Taylor - 8/18/06


  • Hardrock302

    You'll have to create alternative versions of the forms that have parameterless constructors and provide the object via a property before calling Show().

    I'm not sure of the performance of Reflection on CF, you know. Verbose though your original code may be, you might well be better off sticking to it like Matthew says, unless of course you actually don't necessarily know all the names at design time.

    While you're at it, it might be worth creating an enum of form types to use instead of those strings, just to get extra compile-time verification.


  • Tiger Jesse

    You should pass whatever parameters are needed for your constructor. In your case each of your constructors required a ref object parameter so you'd have to pass that in. However if your classes didn't require constructors (probably a good idea) then you would pass null.
  • Lucian Wang

    But is that a better way to do it

    If you use reflection like that, you've thrown compile-time type checking out of the window and replaced it with Visual Basic 6 style runtime type checking. It's also harder to understand the code.

    Is that better I personally think not.

  • nicromi

    I reckon it's fine like that.

  • Tom Frey

    Activator.CreateInstance would help. You need to get the Type so you can call one of the CreateInstance overloads which calls a parameterized constructor:

    string formTypeName = "MyNamespace." + objQuestion.m_objQuestionType.m_strCustomForm;
    Type formType = Type.GetType(formTypeName);
    frm = Activator.CreateInstance(formType, objQuestion) as Form;

    The above code assumes that the forms are all defined in the currently executing assembly; if that's not the case, you'll need to assembly-qualify the value passed to Type.GetType(x). More on that here.



  • dreadjr

    Hi and thanks for the replies all.

    That Generic method looks nice and compact. But what do I pass in as the args parameter for CreateObject()


  • Cpt Rick

    Hi, and thanks for the reply Mark.

    The problem with the code in my initial post is that in the future we will want clients to create their on CustomForm types on the desktop (then synch to the handheld), so I def wont know all the names at design time when the client starts creating these custom forms.


  • Skyman7291

    Matthew: You're probably right.


  • Surrendra

    Gonna throw another spanner in the works here as nothing ever goes straight forward for me :)

    I am actually gonna use this against the Compact Framework V2, which unfortunatley doesn't come with any overloads for CreateInstance(), it Just has the following:

    CreateInstance(Type type);

    So how would I deal with Objects that have Constructors


  • Beware my nasty code! - how can I simplify this?