You can model application-wide state as one object by marking a class as a Singleton; this page is for MDriven Designer users who need one reliably accessible instance of a class.
What is a Singleton?
A Singleton is a design pattern in which a class has exactly one object instance: never zero and never more than one. In an MDriven model, a singleton gives you a model-based location for state that must be available throughout the running system, rather than relying on separate global variables.
For example, a class named SysSingleton can hold an association to the current user. An OCL expression can then read whether that user is an administrator:
SysSingleton.oclSingleton.CurrentUser.IsAdminThe singleton object can have attributes, associations, and code-derived attributes. This lets the model expose relevant runtime information in model context. For example, a singleton can provide the running system URL through an attribute or operation designed for that purpose.
Model a singleton class
In MDriven Designer, create or select the class that must have one instance, then set its tagged value Eco.IsSingleton to true.
After the class is marked as a singleton:
- The class is intended to have one instance only.
- Accessing it with
oclSingletonreturns that instance. - If no instance exists when
oclSingletonis evaluated, MDriven creates one. - Do not design normal application logic around creating or selecting arbitrary instances of this class.
For example, mark SysLogging as both transient and singleton when you need one in-memory logging object for a running application. For the complete logging implementation, see Documentation:Logging OCL in Turnkey.
Access the instance in OCL and EAL
Use oclSingleton as the standard way to access a modeled singleton. It both expresses the intent of the model and ensures that an instance is available.
YourClass.oclSingletonContinue with an attribute, association, or operation as needed:
YourClass.oclSingleton.SomeAttribute
YourClass.oclSingleton.SomeAssociationIn an EAL action, the same expression can be used wherever an object expression is expected. For example, assign a value to an attribute on the singleton:
YourClass.oclSingleton.SomeAttribute := 'Enabled'Do not use allinstances->first for normal singleton access
The expression below can return an existing first object, but it does not communicate singleton intent and does not create an instance when none exists:
YourClass.allinstances->firstUse YourClass.oclSingleton instead. It is the access pattern designed for classes marked with Eco.IsSingleton=true.
Access from code
When code needs all instances of a class, it can retrieve the extent and obtain an object from it:
this.ServiceProvider().GetEcoService<IExtentService>()
.AllInstances(typeof(YourClass))[0]
.GetValue<YourClass>()
This approach indexes the first returned object. It does not provide the create-if-missing behavior of oclSingleton. Use it only when your code context requires extent access and you have accounted for the number of returned instances.
Example: application settings
A singleton is useful for application-wide settings that should be read from the model. MDriven recognizes a class named SysMDrivenMiscSettingsSingleton as a settings singleton when it is modeled as a singleton. Its recognized attributes affect server behavior; see Documentation:SysMDrivenMiscSettingsSingleton for the supported class name and attributes.
For example, a modeled setting can be read through the one object:
SysMDrivenMiscSettingsSingleton.oclSingleton.GlobalToolbarModeKeep recognized class and attribute names unchanged when MDriven or Turnkey expects them. You may add your own attributes and associations, but renaming or removing expected elements can prevent the provided behavior from finding them.
Example: drive ViewModel enablement
A singleton can also provide a shared condition used by a ViewModel. For example, if SysSingleton has a Boolean attribute named AllowAccess, a view-enable expression can use:
SysSingleton.oclSingleton.AllowAccessThis expression evaluates the one shared setting. In a production access-control design, model access information against the relevant user or associated classes when different users require different permissions.
If MDriven reports multiple instances
A class marked as a singleton must not have two persisted objects. This can occur after migration when the destination already contains a singleton and the migrated data also contains one.
If you receive an error that a singleton has multiple instances:
- Start the MDriven OCL Debugger against the database that reports the error.
- Evaluate
ClassName.allinstances, replacingClassNamewith the reported singleton class. - Open a Seeker for that class.
- Delete all but one of its objects.
- Save the changes, then refresh or restart the affected application.
See Documentation:Multiple instances for the troubleshooting procedure.
Design guidance
- Mark only classes that genuinely require one application-wide object as singletons.
- Always use
oclSingletonfrom OCL or EAL to access a modeled singleton. - Keep singleton state focused. A current-user reference or runtime setting is a suitable use; unrelated business data is not.
- Treat persisted singleton data carefully during migration. Verify that the target persistence does not already contain the same singleton object.
- Use a transient singleton when the state must exist only in memory for the running application, such as an in-memory logging buffer.
