🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
Modlr plugin
This page was created by Alexandra on 2018-10-23. Last edited by Wikiadmin on 2026-07-29.

You can extend MDriven Designer and the MDriven Visual Studio extension with a .NET plugin that adds context-menu commands, validates work before code generation, and makes custom OCL operations available at design time.

Choose the extension type

MDriven supports two related ways to extend modeling work:

Need Use Example
Add a command to a model-tree context menu, run code generation checks, or register an OCL operation implemented in .NET. An assembly that implements the Modlr plugin interfaces described on this page. Add a command that renames the selected class, or prevent code generation when a model rule fails.
Inspect model metadata through a derived UI and export the result. A ViewModel plugin file. See Documentation:MDriven Designer and Modlr extensions–exporting data. List every class that has more than three attributes and export the grid to ODS.

A ViewModel plugin runs against the ExtendedModelLayer, the meta-model that represents the model currently open in MDriven Designer. An assembly plugin receives MDriven services and can work directly with the model objects.

Prepare the plugin project

  1. Create a .NET class-library project.
  2. Reference the design-time assemblies from the installed MDriven Visual Studio extension (VSIX).
  3. Implement IModlrPlugin and build the assembly.
  4. Copy the built assembly to the configured plugin directory.
  5. Restart MDriven Designer or Visual Studio so that it loads the assembly.

Use assemblies from the VSIX installation

In newer MDriven builds, assemblies such as MDriven.Handles use different keys in the NuGet packages and in the VSIX. For a design-time plugin, take ModlrPlugins, MDriven.Handles, and other required design-time assemblies from the VSIX installation, not from NuGet packages.

The VSIX assemblies are available only through the VSIX installation. A typical location is:

C:\Users\<user>\AppData\Local\Microsoft\VisualStudio\<VSVersion>\Extensions\<random>\

Use the installation location for the MDriven version that will load the plugin. Do not mix assemblies from a different MDriven installation or from NuGet with the VSIX design-time assemblies.

Install and load the plugin

The plugin infrastructure loads assemblies from its plugin directory. The default path is based on the common application-data location and resolves to:

%ProgramData%\CapableObjects\MDriven\Plugins

The infrastructure creates the directory if it does not already exist. You can override the directory by setting the current-user registry value:

Registry key Value name Value
HKEY_CURRENT_USER\Software\CapableObjects\Modlr PluginPath The full path to the directory from which MDriven should load plugin assemblies.

After copying the assembly, restart MDriven Designer or Visual Studio. The plugin operations appear in the relevant context menu when their enable check returns true. For loading behavior and the configurable path, see Documentation:Plugins in Modlr.

Implement a context-menu plugin

A plugin implements IModlrPlugin. Its ProvideOperations method returns the menu operations that MDriven should offer.

using System.Collections.Generic;
using Modlr.Plugins;

public class DemoPlugin : IModlrPlugin
{
    public string GetName()
    {
        return "Demo plugin";
    }

    public List<IModlrPluginMenuOperation> ProvideOperations()
    {
        return new List<IModlrPluginMenuOperation>
        {
            new OperationActOnClass()
        };
    }
}

Each operation implements IModlrPluginMenuOperation:

public interface IModlrPluginMenuOperation
{
    string GetName();
    void CheckEnableOrExecute(
        IEcoServiceProvider esp,
        bool execute,
        IEcoObject maincontext,
        IEcoObject subcontext,
        out bool enabled);
}

Understand the callback parameters

Parameter Purpose
esp The IEcoServiceProvider for the model. Use it to access MDriven services and model objects.
execute false means MDriven is asking whether the operation is available. true means the user selected the operation and it must perform its work.
maincontext The primary object selected in the MDriven UI.
subcontext A secondary context object when MDriven supplies one.
enabled Set this to true only when the operation applies to the current context.

The callback can be called to check availability and later to execute the command. Keep the availability check free of changes. Make model changes only when execute is true.

Example: enable a command only for a class

The following operation is enabled when the primary context is an Eco.ModelLayer.Class. When the user selects it, the operation appends X to the class name.

using Modlr.Plugins;

public class OperationActOnClass : IModlrPluginMenuOperation
{
    public string GetName()
    {
        return "Operation on class";
    }

    public void CheckEnableOrExecute(
        IEcoServiceProvider esp,
        bool execute,
        IEcoObject maincontext,
        IEcoObject subcontext,
        out bool enabled)
    {
        enabled = false;

        if (maincontext != null &&
            maincontext.AsIObject().AsObject is Eco.ModelLayer.Class)
        {
            enabled = true;

            if (execute)
            {
                var modelClass =
                    maincontext.AsIObject().AsObject as Eco.ModelLayer.Class;
                modelClass.Name += "X";
            }
        }
    }
}

This pattern also supports model checks, imports and exports, report generation, and changes to model elements such as attributes, diagrams, placed classes, state machines, and tagged values. Check the selected context before making a change so that a command is offered only where it is valid.

Run checks around code generation

Implement IModlrPluginImportantEventCallbackHandler when the plugin must run before or after code generation.

public interface IModlrPluginImportantEventCallbackHandler
{
    void ImportantEventAboutToHappen(
        IEcoServiceProvider esp,
        CallbackEventKind eventkind,
        ref bool stop,
        ref string message);

    void ImportantEventHasHappend(
        IEcoServiceProvider esp,
        CallbackEventKind eventkind);
}

public enum CallbackEventKind
{
    CodeGen,
    ForcedCodeGen
}

Use ImportantEventAboutToHappen for checks that must run before generation. Set stop to true and set message when the plugin must block generation and explain why. Use ImportantEventHasHappend for work that must happen after the event.

For example, a plugin can inspect model conventions before CodeGen and stop generation when a required tagged value is missing.

Add a custom OCL operation

Implement IModlrPluginModelAccessOclType to register custom operations with the OCL type service. This makes the operation known to design-time OCL evaluation, including model validation, ViewModels, and the OCL editor. Learn the expression language in OCL.

public interface IModlrPluginModelAccessOclType
{
    void RuntimeModelAccess(IOclTypeService ocl);
}

Register the operation in RuntimeModelAccess:

public void RuntimeModelAccess(IOclTypeService ocl)
{
    ocl.InstallOperation(new CustomOCL_SplitAtSemi());
}

The following example defines SplitAtSemi. It accepts a string and returns the text before the first semicolon.

public class CustomOCL_SplitAtSemi : OclOperationBase
{
    protected override void Init()
    {
        InternalInit(
            "SplitAtSemi",
            new IOclType[] { Support.StringType },
            Support.StringType);
    }

    public override void Evaluate(IOclOperationParameters __Params)
    {
        string value = Support.GetAsString(__Params.Values[0]);
        string[] parts = value.Split(';');
        string first = parts.Length > 0 ? parts[0] : "";
        Support.MakeNewString(__Params.Result, first);
    }
}

For example, 'red;green;blue'.SplitAtSemi() evaluates to 'red'. Because the operation is installed through the plugin interface, an OCL expression using it can be validated and evaluated in design-time tools and during prototyping.

Combine plugin capabilities

One class can implement several plugin interfaces. The following declaration combines menu operations, custom OCL registration, and code-generation callbacks:

public class PluginDemo : IModlrPlugin,
                          IModlrPluginMenuOperation,
                          IModlrPluginModelAccessOclType,
                          IModlrPluginImportantEventCallbackHandler
{
    // Implement the members required by each interface.
}

The MDriven demos include ModlrPluginCodeGenEventsAndCustomOCLOperations, which demonstrates code-generation event handling and custom OCL registration.

Create metadata views without writing an assembly

If your goal is to query and present information about the open model, create a ViewModel plugin instead of a .NET assembly plugin. Open the ExtendedModelLayer through the MDriven Designer plugin/meta-model command, create ViewModels against that meta-model, and save the plugin model in the plugin directory.

For example, the OCL expression below finds classes with more than three attributes:

Class.allinstances->select(c|c.Feature->filterontype(Attribute)->size>3)

After MDriven reloads the plugin files, users can select the ViewModel through the plugin views menu and export grids to ODS. Plugin ViewModels cannot use actions; actions are at a higher abstraction level than these plugin forms. Follow the complete procedure in Documentation:MDriven Designer and Modlr extensions–exporting data.

See also