In my quest to make cross-environmental programming easier, I wondered if I could create three TextField’s (one DesktopTextField, one WebTextField and one MobileTextField) as Properties in the same Class with the same Name.
Normally this would be impossible within the one Project’s environment, but since each Property would only be used in each respective environment (Desktop, Web or Mobile) and never more, due to be setting the Include In Attributes to that environment only, why can’t I have the three Properties with the same name?
Currently I have to define each Object at the start of each Method, leading to much duplication. This way I would be able to define these Properties once in the Opening Event, then use them in any of my Class’ Methods.
Is there a fix, a workaround or a better way?
Use the same strategy for computed property, but use a couple of methods (one for get one to to set)
//Props with the right include settings
Private Property theFieldDesktop As DesktopTextField
Private Property theFieldMobile As MobileTextField
Private Property theFieldWeb As WebTextField
//Methods with the right include settings
Public Function theField() As DesktopTextField
Public Sub theField(assigns value as DesktopTextField)
//and so on for the other targets
//then you code can be:
var value as String=theField.text
(you could create an IDE script to build this structure)
Or use a get/set computed property and use target pragma in the methods
How about having a common super class with all of the common code and subclasses that have the platform specific stuff. You then make a shared factory method on the super which returns the correct subclass like this:
Public Shared Function Create() as superName
Return New WebSubclass
Return New DesktopSubclass
That way the properties can be the same name. Whenever you want to access the properties, you’ll have to cast them however.
Only other way I can think of is to use a different factor method per platform. Then the returned objects would be of the correct type and you could avoid the casting. Oh, and you should make the constructors private so you can’t accidentally create one with “New”.
I would prefer the IDE managing correctly the conflicts, if ANY, and the safeguard is the compiler, saying “X is Already declared here: <the inclusion place>” or “X does not exist” if the interface designer had a bug managing the declaration conflicts letting the user create some bad condition.
Using the suggestions above, I have improved on the Universal Container approach. It still requires creating three Containers with identical field layouts (for Desktop, Web and Mobile), but code management is much easier.
In the example zip file (linked below) I have a single Window and a single Container for each Project (Desktop, Web and Mobile) with a shared external Class. The Container contains a couple of fields, but no Event Handlers at all, as these Events are all contained in the external Class.
In the sample, run each project and see that each field is defined in the Class, including an Event Handler, then the main field is updated in one line:
FirstName.Text = "It works!"
The external Class has a Property for the Container called ‘myContainer’, as this will give the Class access to all the fields. Every field on the Container is represented in the Class as a ‘Convert to Method Pair’, but:
It has three possible assignments (eg DesktopTextField, WebTextField and IOSTextField)
It ‘assigns value as Object’ and returns the corrected Value based upon the respective environment (Desktop, Web and Mobile)
There are three corresponding Shared Properties per field, one per respective environment (Desktop, Web and Mobile)
You need to set the ‘Include in Attributes’ for the Class’ Property field names and Shared Properties to their respective environments (to stop compile errors) eg DesktopTextField to Desktop 32/64 only, WebTextField to Web 32/64 only and MobileTextField to iOS 64 only.
In the Class’ doOpening Method, there will be a lot of work mapping the Container fields to the Class’ fields, but this needs to be done only once.
The advantage of this technique is:
Every control Event Handlers can be mapped into the Class making it the sole location of all logic for each Container field event ie change it once = change it everywhere. The Container fields can still have default attributes.
All Methods within the Class to perform actions can refer to the Container fields by their base-name (eg FirstName not myContainer.FirstName)
Having one Class per Container should stop the Class becoming too large and unwieldy.
You can add new Event Handlers to a field once (in the Class) rather than having to add/manage multiple UI’s.
Debugging is much easier since all changes to a field’s actions or Container Methods are fully within the Class, removing all duplication of code.