views:

612

answers:

1

I have a class in my Prism/CAL application which generates a form for users to fill in data.

The form is defined by an XML file like this:

<area idCode="general" title="General">
    <column>
        <group title="Customer Data">
            <field idCode="title" requiredStatus="true">
                <label>title</label>
                <fieldType>Title</fieldType>
            </field>
            <field idCode="firstName" requiredStatus="true">
                <label>First Name</label>
                <fieldType>Text</fieldType>
            </field>
            <field idCode="lastName" requiredStatus="true">
                <label>Last Name</label>
                <fieldType>Text</fieldType>
            </field>
            <field idCode="email" requiredStatus="true">
                <label>E-Mail</label>
                <fieldType>Email</fieldType>
            </field>
            ...
        </group>
     </column>
    </area>

the form needs to load specific controls which correspond to each field type in the XML, e.g.

  • Title (shows a dropdown: Mr., Mrs., Dr., etc.)
  • Text (simple textbox)
  • Email (textbox with e-mail validation)
  • ZipCode (textbox with zipcode validation)

I want to make each control a separate module which gets loaded so that e.g. the ZipCode module would exist in a Modules directory as a file:

ZipCode.dll

which is just a simple textbox control that validates based on zipcode, but developers could make another control called:

ZipCodePlus.dll

which inherits the same interface but provides a pop-up geo-earth selector for zipcodes. As soon as a customer replaced ZipCode.dll with ZipCodePlus.dll, all of his forms would have this new functionality for searching for zip codes.

However, I'm having trouble visualizing how this will be technically implemented, since as my form class is parsing the XML, it instantiates the classes which provide the functionality for the controls, but in order to instantiate the class, I have to have a reference to it:

SmartFormFieldZipCodePresenter smartFormFieldEmailPresenter
    = container.Resolve<SmartFormFieldEmailPresenter>();

But how can I instantiate it dynamically, i.e. with the name of the class as a string, and if that class does not exist then it will throw an appropriate exception, e.g. something like this:

PSEUDO-CODE:

try {
    var smartFormFieldZipCodePresenter
     = container.Resolve("smartFormFieldZipCodePresenter");
}
catch (ModuleDoesNotExistException) {
    ...
}
+1  A: 

It seems you are very close to a technical solution to your problem. I would simply create an interface - IZipCodePresenter - and in my ZipCode.dll or ZipCodePlus.dll module startup, register the implementation.

Container.RegisterType<IZipCodePresenter, StandardZipCodePresenter>();

Then in your parser, resolve the instance like:

var zipCodePresenter = container.Resolve<IZipCodePresenter>();

Assuming no instances are registered for the interface, an exception will be thrown. Otherwise, you will get the last registered concrete implementation of IZipCodePresenter. Note that an exception will only be thrown if you try and register an interface. If you attempt to register a class with Unity, it will create an instance based on the Lifetime Manager policy.

If you wanted to go further with this, you could create an interface... something like IDynamicPresenter. You could then register based on a known string (defined in your infrastructure project).

Container.RegisterType<IDynamicPresenter, StandardZipCodePresenter>(PresenterName.ZipCodeControl);
Container.RegisterType<IDynamicPresenter, StandardEmailPresenter>(PresenterName.EmailControl);

and then resolve like the following:

var zipCodeControl = Container.Resolve<IDynamicPresenter>(PresenterName.ZipCodeControl);
var emailControl = Container.Resolve<IDynamicPresenter>(PresenterName.EmailControl);

I prefer the former solution, but this is certainly a valid option.

Hope this helps!

P.s. This sounds like an interesting idea... I'd be interested to hear how you get on with the implementation. You could even move one step further and create a whole XAML builder framework based on some of the concepts in ASP.NET MVC. It could facilitate ease in testing, yet have the power of WPF. Good luck!

Brad Leach