Making a relation between the same content class reflexive

If you create a relation where the parent and child content class is the same, you often need the relation to reflexive.

A reflexive relationship can be defined as:

"A reflexive relationship is bidirectional with both the cause and the effect affecting one another"

For example, if you have a content class called TestArticle. TestArticle needs a property that contains a list of articles that is related. So we create a many-to-many relation where parent and child content class is TestArticle. 

Normally we have to create two properties when we create a relation, one for both sides of the relation. When we have a relation between the same content class we still have to add two properties. 

In this example, the the properties can be called "RelatedArticles" and "ArticlesRelatingToThisArticle". The default way a relation works is that if you add an article to the RelatedArticles property of another article, the article that was added gets a relation back to the other article through the ArticlesRelatingToThisArticle property.

But sometimes you want the added article to also get a relation to the other article through the "RelatedArticles" property. This is called a reflexive relationship: if an article adds a relation to another article, that article adds a relation back.

The extend the functionality of the relation to support this, you need to 

//The class name must be the same as the class name that represents the relation. The class name is the same as the name of the relation in the Relations tab in //the semantics module.
    public partial class RelRelatedArticles : WAF.Engine.Content.RelationBase {
        public override void OnChangeAfterUpdate(ContentBase content, NodeRelationsDataValue dv, List<ICKeyNxxC> added, List<ICKeyNxxC> removed, MemDefProperty propDef, MemDefRelation relDef) {
            if (propDef.Id == AdvancedArticle.PropertyIdRelatedArticles) {
                AdvancedArticle art = (AdvancedArticle)content;
                foreach (ICKeyNxxC bKey in added) {
                    AdvancedArticle relArt = content.Session.GetContent<AdvancedArticle>(bKey.NodeId);
                    if (!relArt.RelatedArticles.Contains(art.NodeId)) {
                        relArt.RelatedArticles.Add(art.NodeId);
                        relArt.UpdateChanges();
                    }
                }
                foreach (ICKeyNxxC bKey in removed) {
                    AdvancedArticle relArt = content.Session.GetContent<AdvancedArticle>(bKey.NodeId);
                    if (relArt.RelatedArticles.Contains(art.NodeId)) {
                        relArt.RelatedArticles.Remove(art.NodeId);
                        relArt.UpdateChanges();
                    }
                }
            }           
            base.OnChangeAfterUpdate(content, dv, added, removed, propDef, relDef);
        }
    }

Explanation of the code

The OnChangeAfterUpdate method is called after a relation has been changed during an update.

For each RelatedArticle we have added or removed, we add or remove the current article from the RelatedArticle property of the related articles.