How to get a unique name for connectors across a whole model?

Joeul asks an interesting question in his forum post. reference relationships' names are not normally unique across the whole model, but only to the 2 elements they link. How to change this behavior?

Here is how to do to get unique name for reference relationships across the model. This is also the opportunity of explaining how to use the Name providers.

Let’s suppose that I have a simple DSL named “GloballyUniqueRelationshipName” which I unfolded from a Minimal language:

  1. Add a Name property (of type String) to the ExampleElementReferencesTargets Relationship

  2. Set the IsElementName property of this Name domain property to True (using the property window)

  3. In the DSL explorer, set the UseFullForm property of the ExampleElementReferencesTargets serialization under the ExampleElement in the Xml Serialization behavior to true (because now our relationship has domain properties) as shown on the picture below:image

  4. In the DSL project, add a custom code folder in which you will add a new class named MyNameProvider, with the following content:

     using System;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.VisualStudio.Modeling;
    
    namespace Company.GloballyUniqueRelationshipName
    {
     /// <summary>
     /// Custom name provider that ensures that every link instance has a unique name
     /// </summary>
     internal class MyNameProvider : ElementNameProvider
     {
      public override void SetUniqueName(ElementLink link, DomainRoleInfo indexingDomainRole, string baseName)
      {
       if (link == null)
       {
        throw new ArgumentNullException("link");
       }
    
    
       baseName = "MyBaseName";
    
       IDictionary<string, ModelElement> allSiblings = link.Store.ElementDirectory.FindElements(link.GetDomainClass())
                                                                               .Where(l => l != link)
                                                                               .ToDictionary(l => l.GetDomainClass().NameDomainProperty.GetValue(l).ToString());
    
    
       if (this.DomainProperty.PropertyType == typeof(string))
       {
    
        this.SetUniqueNameCore(link, baseName, allSiblings);
       }
       else
       {
        this.CustomSetUniqueNameCore(link, baseName, link.Store.ElementDirectory.FindElements(link.GetDomainClass()));
       }
    
      }
     }
    }
    
  5. In the DSL Explorer, add a new external type (right clicking on the root node), named MyNameProvider and of namespace Company.GloballyUniqueRelationshipName

  6. Change the ElementNameProvider property of the Name domain property of your ExampleElementReferencesTargets to MyNameProvider 

  7. You are done!

    If you run your DSL in the experimental hive, the links you will create will be named “MyBaseName1”, “MyBaseName2”, and so on.

      
    

Note that this sample can be improved to apply this processing to links of a given class only (here we apply it to every links)