The UML-to-C# transformation adds the @generated tag to the following elements:
When you rerun a UML-to-C# transformation, by default, the transformation does not overwrite method bodies that the transformation generates, or that a user creates. The transformation always preserves method bodies, whether or not you remove the @generated tag.
Although the transformation always preserves method bodies, you must remove the @generated tag from a method to preserve structural changes to the method. For example, you must remove the @generated tag for the method if you change the method signature, add initializers to a constructor, add exceptions to methods, or add comments to the source code.
You can also add code to the user-defined sections that the transformation creates. The transformation does not overwrite or remove code that you specify within a user-defined section.
Any user code you enter directly after any of the above listed elements, without any intervening blank lines, is interpreted by a transformation as the post-user-code of the element directly before it. All user-code you enter after a blank line is interpreted by a transformation to be the pre-user-code for the succeeding element.
Although the @generated tag and user-defined, pre-user-code, and post-user-code sections offer flexibility, to avoid possible problems, you should make structural changes to the source UML model instead of the generated code. You can also run the reverse transformation to add new methods or attributes to the source UML model.
Some variations of pre- and post-user-code implementation exist for typical elements, namespaces, and comments.
Typical elements
Consider the following code snippet:
#if DEBUG
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_KBkvkMtZEd2IB4RiswwPkg
// ]
public void Operation1()
{
//TODO: Auto-generated method stub
throw new System.NotImplementedException();
}
#endif
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_UxwLEc2-Ed2itJx87rzLyg
// ]
public void Operation2()
{
//TODO: Auto-generated method stub
throw new System.NotImplementedException();
}
In the above example, the #endif directive is the post-user-code section of the Operation1 element. If there are no blank lines between two elements, all the code from the end of the first element to @generated, @C#_transform [, or the beginning of the next element is considered to be post-user-code of the first element. An exception to the space-delineation rule is if there is a space after an element followed by user-code, but there are no additional elements, then the user-code is attached as the post-user-code of the preceding element, as in the following example:
public class Class1
{
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_KBkvkMtZEd2IB4RiswwPkg
// ]
public void Operation1()
{
//TODO: Auto-generated method stub
throw new System.NotImplementedException();
}
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_UxwLEc2-Ed2itJx87rzLyg
// ]
public void Operation2()
{
//TODO: Auto-generated method stub
throw new System.NotImplementedException();
}
#endif
}
Namespaces and #define statements
Elements inside a namespace can be split, or merged with elements of the same namespace, across compilation units. As a general principle, if a composite-type declaration, enumeration, or delegate inside a namespace is moved to another compilation unit, for example, by using mapping models, the element carries the user code of the enclosing namespace from the source unit to the namespace in the target unit, and appends it to the existing user code on the target.
Consider the following sample code for Class1.cs:
public class Class1
{
}
#region com-Class1
namespace com
{
public class Class3
{
}
public class Class4
{
}
}
#endregion
Class2.cs:
public class Class2
{
}
#region com-Class2
namespace com
{
public class Class5
{
}
}
#endregion
If you modify the mapping model so that com.Class4 is moved to Class2.cs, the resulting code after a forward transformation would be generated like the following example:
Class1.cs
public class Class1
{
}
#region com-Class1
namespace com
{
public class Class3
{
}
}
#endregion
Class2.cs
public class Class2
{
}
#region com-Class2
#region com-Class1
namespace com
{
public class Class4
{
}
public class Class5
{
}
}
#endregion
#endregion
The pre- and post-user-code elements #region com-Class1 and #endregion are added to the existing user code by the transformation. Note that pre-user-code is appended while post-user-code is prepended.
Similarly, when a composite type declaration or namespace is moved from one compilation unit to another through mapping models, the #define and #undef statements from the source unit are appended onto the target unit.
Comments
Comments which are located above a preprocessor directive are assumed to be relevant to it, and are preserved as user code as well. The ordering of comments and preprocessor directives is maintained. Consider the following code snippet:
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_0o-fIOhIEd2SdrLLRilfrw
// ]
public class Class1
{
#region c
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_S4TRgOkaEd2owca4Ri32gw
// ]
public void Operation2()
{
//TODO: Auto-generated method stub
throw new System.NotImplementedException();
}
//region ends
#endregion
//comment for a
#region a
//comment for b
#region b
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_vZgVUOhjEd2vc-H9Qq-k_Q
// ]
public void Operation1()
{
//TODO: Auto-generated method stub
throw new System.NotImplementedException();
}
//end b
#endregion
//end a
#endregion
}
The code from after Operation2() until the #endregion directive is assigned as post-user code for the method. After the occurrence of a blank line, everything from there until the last preprocessor directive is assigned as pre-user code for Operation1(). Note that this includes comments as well. Pre-user code will have the comment //region ends and post-user code will have the comments //comment for a and //comment for b. This preserves any comments that are relevant to the directives.
UML documentation pertaining to transformation and model properties are not stored as user code. Instead, the UML documentation is stored in the model. If preprocessor directives are included as non-modeled elements, when you reapply a transformation, documentation is preserved for all non-modeled elements, while the documentation for modeled elements is taken from the Documentation tab in the model.
When you rerun the UML-to-C# transformation after adding code to pre-user and post-user code sections, the transformation reorders certain elements in the source code.
For example, in the following code snippet that was generated by the UML-to-C# transformation, a software developer added an attribute named attribute1 between Operation2() and Operation1().
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_GXpy8Nr5Ed2zKbxEG_6cmQ
// ]
public class Class2
{
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_tnNPwNsGEd2zKbxEG_6cmQ
// ]
public void Operation2()
{
//TODO: Auto-generated method stub
throw new System.NotImplementedException();
}
#if DEBUG
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_HEXH8Nr5Ed2zKbxEG_6cmQ
// ]
private Object attribute1;
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_HYxRsNr5Ed2zKbxEG_6cmQ
// ]
public void Operation1()
{
//TODO: Auto-generated method stub
throw new System.NotImplementedException();
}
#endif
}
When the developer reruns the UML-to-C# transformation, the attribute named attribute 1 moves to the top of the code, along with the attached pre-user code. The modified code then looks like the following example:
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_GXpy8Nr5Ed2zKbxEG_6cmQ
// ]
public class Class2
{
#if DEBUG
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_HEXH8Nr5Ed2zKbxEG_6cmQ
// ]
private Object attribute1;
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_tnNPwNsGEd2zKbxEG_6cmQ
// ]
public void Operation2()
{
//TODO: Auto-generated method stub
throw new System.NotImplementedException();
}
// @generated
// @C#_transform [
// _URI=platform:/resource/GraphicsLibraryProject/GraphicsModel.emx#_HYxRsNr5Ed2zKbxEG_6cmQ
// ]
public void Operation1()
{
//TODO: Auto-generated method stub
throw new System.NotImplementedException();
}
#endif
}
The reordering of elements changes the result of the pre-processor, such as the “#if” loop in the above example and can cause compilation errors. Developer must be aware that the code preservation functionality is unpredictable if you reorder elements manually.