XAF best practices 2017-02

In the last post I described how i like to layout Modules and the csproj file. Today i like to go on with editors.
For this post i will implement a custom LabelEdit that will represent a caption that can be changed in code. So i will highlight how to implement an editor and the business objects.

BusinessObjects

Before i start with implementing the Editor i will start with the basics of PersistentObjects.
I mostly used XPO so far, so i will focus on them first. In a later blog post I try to cover some of the EntityFramework basics.

So first of all I like to provide common base classes for XPO in a own Module. In my case i will implement them in an assembly called Scissors.Xpo similar to DevExpress.Xpo. But if you don't want to write your very own base library you can implement this in a Common Library called YourCompany.Persistent.Base. This should only hold base classes used by every BusinessModule of your Application.

Next i implement an BusinessObject based on the ScissorsBaseObjectOid class. This should be fairly simple, but there is a catch. I like to keep my BusinessObjects in a different assembly. Normally a BusinessModule consists of 3 assemblies:

YourCompany.ExpressApp.Module

YourCompany.ExpressApp.Module.Win

YourCompany.ExpressApp.Module.Web

Based on domain driven design (DDD) i really hat this approach, cause it leads to a massive god modules. They become harder and harder to maintain.
So i like a more modular approach.

First of all: the ExpressApp in the namespace can lead to very weird conflicts when developing the application. So i like to use a more general name for it. So we go for Modules. Another thing i like to add is 2 secondary assemblies. One for the BusinessObjects and one for the Contracts.
In my case i will implement this in my Scissors.FeatureCenter project. So my assemblies will look like this:

Scissors.FeatureCenter.Modules.LabelEditorDemos.Contracts

Scissors.FeatureCenter.Modules.LabelEditorDemos.BusinessObjects

Scissors.FeatureCenter.Modules.LabelEditorDemos

Scissors.FeatureCenter.Modules.LabelEditorDemos.Win

I omitted the Web assembly, cause at this moment i have no plans to add a Web implementation so far.
The purpose of the contracts assembly is to deal with inter module communication. This assembly should provide all public contracts that an business module can offer.

but lets start with the Scissors.FeatureCenter.Modules.LabelEditorDemos.BusinessObjects project.

As you can se we have no strings floating around. One thing that you can argue about is the name of the name of the persistent table and column. You can fix them to avoid later problems with refactoring. I will highly recommend this if you are porting a legacy database. You also can introduce a guard when starting the application if you forget to add the PersistentAttribute with an explicit name.

Next step is to provide a convenient list of types this module exports. Lets call the list LabelEditorDemosBusinessObjects:

Editors

So enough basics. Let's get the editor running. We start again with a new module, cause i really like the idea of small, reusable modules. Especially for editors. Often they start small, but over time so much configuration and other functionality accumulates, so i put them always in separate modules/assemblies.

So let's implement the PropertyEditor. The goal is to use the LabelControl out of the DevExpress.XtraEditors assembly. We want to have HTML formatting and word wrapping enabled, so we can display some information to the user.

First of all we need to derive our PropertyEditor from DevExpress.ExpressApp.Win.Editors.WinPropertyEditor cause the LabelControl is not derived from BaseEdit.

As you can see, there is not much going on, deriving from ScissorsBaseModuleWin and register the PropertyEditor. I like to delegate the registration to an extension method, so the Module does not get to bloated, and it's clear to see what is going on. So have a look at the LabelStringEditorDescriptorsFactoryExtentions. I know it's quite a verbose name, but on the other hand it's clear to everybody on the team what this class is supposed to do.

The EditorAliasesLabelEditor class is defined in the Scissors.ExpressApp.LabelEditor.Contracts assembly, so we avoid strong coupling.

So first of all the EditorAlias is defined in the EditorAliasesLabelEditor.Consts.LabelStringEditor constant. It's value is LabelStringEditor. The reason we define a separate constant is if we need to access the string from an attribute.

The EditorAliasesLabelEditor.LabelStringEditorreadonly string is for ease access.

The EditorAliasesLabelEditor.Types.LabelStringEditor property is to avoid coupling, and could be probably be made internal with the InternalsVisibleToAttribute but I think this is more harmful than good.

So in the static constructor of the LabelStringEditorDescriptorsFactoryExtentions we register the type of the editor. The other 2 parts are easy. Register the EditorAlias to the type string and make it the default alias. Then register the editor with the alias to the string type and make sure it's not registered as the default editor for the type string.

Try it out

So first of all we need to update the LabelEditorDemosFeatureCenterWindowsFormsModule module to reference the LabelEditorWindowsFormsModule. But wait? Will this raise coupling? Yes it does. I'll address this problem is a later blog post.