Implementing a framework validator

To proper validate the project against the functionality supported by a target framework, framework validators are used. Framework validators are classes deriving from SD.LLBLGen.Pro.ApplicationCore.Extensibility.FrameworkValidatorBase, which is an abstract class in the ApplicationCore assembly. The validator assembly's location and filename is specified in the framework's .framework file.

During the second stage of the project validation process, the framework specific validator as specified in the .framework file of the target framework of the project is instantiated and asked to verify the project. This is done by calling the validator's Validate method.

Reporting errors / warnings

The LLBLGen Pro designer supports an error / warning messaging system. All errors and warnings are reported as messages to the central message dispatcher. The messages are distributed to subscribers, among them the Error List pane in the LLBLGen Pro designer. The FrameworkValidatorBase class contains several methods to make it easy to construct and send error, warning and normal messages. Normal messages end up in the Application Output pane. An error or warning message is called a Correctable message. A correctable message can contain suggestions or steps.

After a message has been constructed and is ready to be posted, call the FrameworkValidatorBase method DispatchCorrectableMessage(). When you detect an error and report an error message, your validate method has to return false. This signals to the validate control logic that at least an error has been posted and the process has to be stopped at the end of the validation stage and can't proceed.

Correctable message corrections are added by calling the AddCorrection method on the CorrectableMessage created. A correction can be a lambda containing correction, or a go location containing correction. A step in a list of suggestions is also added with AddCorrection, but doesn't contain any lamdba/go location object. In general corrections are lambda's/go location corrections so the user can directly take action by clicking the correction in the Errors and Warnings list.

To open an editor, a SourceLocationData derived object has to be provided to the RaiseGoLocationRequested method of the message dispatcher (see example below). Main objects in a project, like entity definitions, provide such a go location object themselves. Other objects, like relationships require an instantiation of their source location data subclass, which are available in the namespace SD.LLBLGen.Pro.ApplicationCore.MessageReporting.SourceLocationDataClasses in the ApplicationCore assembly.

Example

The following example is a validation provided by the FrameworkValidatorBase class itself. It illustrates a simple validation and how an error message is posted as well as how a correction is added to the error message. This correction opens the entity editor of the entity which contains the error. The AsFormatted extension method is found in the BCLExtensions assembly shipped with LLBLGen Pro and which is licensed to LLBLGen Pro licensees under the BSD license.

/// <summary>
/// Reports an error if the subElement name specified is equal to the name of the containingElement specified
/// </summary>
/// <param name="subElementName">Name of the sub element.</param>
/// <param name="containingElement">The containing element.</param>
/// <param name="error">if set to <c>true</c> a conflict is reported as an error, otherwise as a warning.</param>
/// <returns>
/// true if no error was dispatched, false otherwise
/// </returns>
protected virtual bool ReportSubElementNameEqualToContainingElementNameAsCorrectableMessage(
                                     string subElementName, GroupableModelElement containingElement, bool error)
{
    bool toReturn = true;
    if(string.IsNullOrEmpty(subElementName) || (containingElement == null))
    {
        return true;
    }
    if(subElementName.ToLowerInvariant() == containingElement.Name.ToLowerInvariant())
    {
        toReturn = !error;
        var message = this.CreateCorrectableMessage(error, true, 
                "The {0} '{1}' contains field '{2}', however the field has the same name as the {0}, something which isn't supported by the target framework.",
                containingElement.GetElementNameForErrorReporting(), containingElement.FullName, subElementName);
        message.AddCorrection("Open the {0} '{1}' in its editor and change the name of field '{2}' into something else."
                    .AsFormatted(
                        containingElement.GetElementNameForErrorReporting(), 
                        containingElement.FullName, subElementName),
                1, () => MessageManagerSingleton.GetInstance().RaiseGoLocationRequested(
                        containingElement.CreateSourceLocationDataObject()));
        this.DispatchCorrectableMessage(message);
    }
    return toReturn;
}