MSDN > 論壇首頁 > Visual Studio Extensibility > How to Use Path Syntax and Element Merge Directives
發問發問
 

一般討論How to Use Path Syntax and Element Merge Directives

  • 2006年6月9日 下午 04:47Alan Cameron Wills -MSFT使用者勳章使用者勳章使用者勳章使用者勳章使用者勳章
     

    (Answers to a question in another thread, that I thought might be of wider interest.)

    Path syntax is very simple, though it's rather verbose. Eventually the intention is to hide it behind a nicer UI.

    Let's look at a ShapeMap example from the Components solution template, the one mapping InPortShape to InPort.

    You can see this if you generate a new DSL, choosing "Component model" in the wizard. Then open DSLDefinition.dsl, and in the DSL Explorer window, look under Diagram/ShapeMaps and select the first ShapeMap. There are some details in the normal Properties window, and more details in the DSL Details window. (If you don't see that, look under the View>Other Windows menu for DSL Details.)   The Parent Element Path shows in the General tab of DSL Details, when you have that ShapeMap selected in the DSL Explorer.

    Each path has one or more segments, separated by slashes.

    Each segment is either a hop from an object to a link, or from a link to an object. So generally, they come in pairs: hop from object to link, and then onto the object at the other end.  (Actually, links -- that is, instances of relationships -- can also be the source or target of a relationship; but in most cases, a path goes link/object/link/object...)

    Each segment starts with a relationship name. If it's an object-to-link hop, it is "Relationship . Property"; if it's a link-to-object hop, it's "Relationship ! Role".

    In the InPort shape map example, the parent element path begins

        ComponentHasPorts.Component

    From the main classes diagram, we can see that InPort is a subclass of ComponentPort, and has a relationship ComponentHasPorts, and the property is indeed called Component.

    When writing C# against this model, you can jump across a link in one go, using the property that the relationship generates on each of the classes it relates:

         InPort port; ...  Component c = port.Component;

    but in Path Syntax, you have to do both hops explicitly. This makes it easier to get at the intermediate link if you need to. So we complete the hop from the link to the Component:

        ComponentHasPorts.Component / ! Component

    (You can omit the relationship name where it's the same as the previous segment.)

    --------

    Notice that the name you use for the object-to-link hop is the PropertyName defined on the role -- that's the name you see on the main diagram next to the corresponding line from the object's class. If you click on that role line, you'll see it in the properties window under PropertyName.

    The name you use for the link-to-object hop is the role name defined on the Relationship for the destination end. So in the main diagram, if you click on the line on the other side of the Relationship, you'll see it listed as that role's Name in the properties window.  Often the PropertyName and the Name of opposite roles are the same.

    In programming, the PropertyName is the name you use if you have an instance of an object class and want to traverse the relationship; while the role Name is the name you use if you have an instance of a relationship, and you want the object at one end.

     ----

    In some contexts, such as Element Merge Directives, only the object-to-link part of the path is required. 

    An Element Merge Directive tells the framework how to add one object to another - typically when you pull the object off the toolbox. So generally, the model class that is mapped to the diagram (in the same example, ComponentModel) has an EMD for each of the other classes. The EMD tells what links must be created when the merging object is merged into the target object: for example, when a Comment is merged onto a ComponentModel, a link of the ComponentModelHasComments relationship is created, and from the ComponentModel's point of view, that means adding to its Comments property. So the EMD's links list has:

       ComponentModelHasComments.Comments

    --------

    Not all EMDs are on the model root, though. In the Classes DSL, you can drag an Attribute or an Operation onto a Class: so the Class class (well - it's called ModelClass, to avoid confusion!) has an ElementMergeDirective for each of those.

    ------

    For a more complex EMD path, see the Task Flows template. There, you can drag for example a Comment from the toolbox onto an Actor (represented by a swimlane); but the link that's constructed isn't from the Actor, it's from its parent model, called TaskFlowGraph. So the path begins by navigating to the parent model; the last segment tells the actual link to construct:

        TaskFlowGraphHasActors.TaskFlowGraph / ! TaskFlowGraph
          / TaskFlowGraphHasComments.Comments

    In the same DSL, dropping a TaskFlowElement onto an Actor creates two links: one to the model root, and another to the Actor it was dropped onto. So there are two link paths in the EMD under Actor for TaskFlowElement.