Reference:
https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/dev-tools/author-best-practice-rules
Authoring Best Practice checks that use XML based input
http://www.agermark.com/2017/01/authoring-best-practice-checks-that-use.html
Reference Content from agermark.com
Your Best Practice class needs to extend either DetectorWithXMLDataFile or MetadataDetectorWithXMLDataFile depending on the type of your check. In this case we extend MetadataDetectorWithXMLDataFile since we will be looking at table extension names.
Included in your solution you need to add a data contract class for the XML file. This class must extend from RulePatternsBase.
The framework and the base classes will then do the rest of the work with loading the XML file, de-serialize it and caching it.
Here is the code:
And here is the code for the diagnostic item:
https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/dev-tools/author-best-practice-rules
Authoring Best Practice checks that use XML based input
http://www.agermark.com/2017/01/authoring-best-practice-checks-that-use.html
Reference Content from agermark.com
Authoring Best Practice checks that use XML based input
In AX7 you can pretty
easily write and deploy your own Best Practice checks. The process of doing so
is described in this article on the wiki.
Some of the standard Best Practice checks use XML files as input. These XML files are found under your local packages folder, in ..\PackagesLocalDirectory\Bin\BPExtensions\RuleXml
The following is an example of how you can write your own Best Practice check that uses an XML file as input. The check itself is used to check the naming of table extensions. We want to check that a certain prefix is part of the name, and that it is put in the correct place in the overall name. The prefix to look for is specified in the XML file.
Some of the standard Best Practice checks use XML files as input. These XML files are found under your local packages folder, in ..\PackagesLocalDirectory\Bin\BPExtensions\RuleXml
The following is an example of how you can write your own Best Practice check that uses an XML file as input. The check itself is used to check the naming of table extensions. We want to check that a certain prefix is part of the name, and that it is put in the correct place in the overall name. The prefix to look for is specified in the XML file.
The file is stored in
..\PackagesLocalDirectory\Bin\BPExtensions\RuleXml and the name is
MVPProductPrefix.xml. The name is important, as a reference is made to it from
the code.
Your Best Practice class needs to extend either DetectorWithXMLDataFile or MetadataDetectorWithXMLDataFile depending on the type of your check. In this case we extend MetadataDetectorWithXMLDataFile since we will be looking at table extension names.
Included in your solution you need to add a data contract class for the XML file. This class must extend from RulePatternsBase.
The framework and the base classes will then do the rest of the work with loading the XML file, de-serialize it and caching it.
Here is the code:
namespace MVP.AX.BestPracticeCheckExtensions
|
|
{
|
|
using System;
|
|
using System.Text.RegularExpressions;
|
|
using Microsoft.Dynamics.AX.Framework.BestPractices.Extensions;
|
|
using Microsoft.Dynamics.AX.Metadata.Upgrade.Common;
|
|
using System.Runtime.Serialization;
|
|
|
|
[BestPracticeRule(
|
|
InvalidExtensionnameDiagnosticItem.DiagnosticMoniker,
|
|
typeof(Messages),
|
|
InvalidExtensionnameDiagnosticItem.DiagnosticMoniker
+ "Description",
|
|
BestPracticeCheckerTargets.TableExtension),
|
|
RuleAttributes("MVPProductPrefix.xml")]
|
|
public class TableExtensionNameCheck : MetadataDetectorWithXMLDataFile<Microsoft.Dynamics.AX.Metadata.MetaModel.AxTableExtension, EGProductPrefix>
|
|
{
|
|
/// <summary>
|
|
/// This method is called with the top level
table extensions - everything else is ignored.
|
|
/// </summary>
|
|
/// <param name="tableExtension">A tableExtension
instance to check for BP violations.</param>
|
|
protected override void RunChecksOn(Microsoft.Dynamics.AX.Metadata.MetaModel.AxTableExtension tableExtension)
|
|
{
|
|
visitTableName(tableExtension.Name);
|
|
}
|
|
|
|
private void visitTableName(string tableName)
|
|
{
|
|
string requiredPrefix = base.RulePatterns.Prefix;
|
|
string dotExtensionPattern = @"\w+." + requiredPrefix + "Extension";
|
|
var match = Regex.IsMatch(tableName, dotExtensionPattern);
|
|
|
|
if (!match)
|
|
{
|
|
// Didn't fint the
correct pattern in the table extension name
|
|
// Build a diagnostic
...
|
|
InvalidExtensionnameDiagnosticItem diagnostic = new InvalidExtensionnameDiagnosticItem(
|
|
ModelElementPathBuilder.CreatePathForTable(tableName),
|
|
"TableExtension",
|
|
null,
|
|
tableName);
|
|
|
|
// ... and report the
error.
|
|
this.ExtensionContext.AddErrorMessage(diagnostic);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Serializable, DataContract(Name = "MVPProductPrefix", Namespace = "")]
|
|
public class MVPProductPrefix : RulePatternsBase
|
|
{
|
|
/// <summary>
|
|
/// This class is the data contract for the
XML file
|
|
/// </summary>
|
|
|
|
// Fields
|
|
[DataMember(Name="Prefix")]
|
|
public string Prefix;
|
|
}
|
|
}
|
And here is the code for the diagnostic item:
using
System;
|
|
using
System.Collections.Generic;
|
|
using
System.Runtime.Serialization;
|
|
using
System.Xml.Linq;
|
|
using
Microsoft.Dynamics.AX.Metadata.XppCompiler;
|
|
|
|
namespace
MVP.AX.BestPracticeCheckExtensions
|
|
{
|
|
/// <summary>
|
|
/// Class that describes the error where invalid extension
names are invalid
|
|
/// </summary>
|
|
[DataContract]
|
|
class InvalidExtensionnameDiagnosticItem : CustomDiagnosticItem
|
|
{
|
|
private
const
string
InvalidExtensionnameKey = "Extensionname";
|
|
public
const
string
DiagnosticMoniker = "InvalidExtensionname";
|
|
|
|
public
InvalidExtensionnameDiagnosticItem(string path, string elementType, TextPosition textPosition, string invalidExtensionname)
|
|
: base(path,
elementType, textPosition, DiagnosticType.BestPractices, Severity.Warning, DiagnosticMoniker,
Messages.InvalidExtensionname, invalidExtensionname)
|
|
{
|
|
// Validate parameters.
|
|
if
(string.IsNullOrWhiteSpace(invalidExtensionname))
|
|
{
|
|
throw new ArgumentNullException("invalidExtensionname");
|
|
}
|
|
|
|
this.InvalidExtensionName
=
invalidExtensionname;
|
|
}
|
|
|
|
public
InvalidExtensionnameDiagnosticItem(Stack<Ast> context, TextPosition textPosition, string invalidExtensionname)
|
|
: base(context, textPosition,
DiagnosticType.BestPractices, Severity.Warning, DiagnosticMoniker, Messages.InvalidExtensionname,
invalidExtensionname)
|
|
{
|
|
// Validate parameters.
|
|
if
(string.IsNullOrWhiteSpace(invalidExtensionname))
|
|
{
|
|
throw new ArgumentNullException("invalidExtensionname");
|
|
}
|
|
|
|
this.InvalidExtensionName
=
invalidExtensionname;
|
|
}
|
|
|
|
[DataMember]
|
|
public
string
InvalidExtensionName { get; private set; }
|
|
|
|
// Serialization support
|
|
public
InvalidExtensionnameDiagnosticItem(XElement element)
|
|
: base(element)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Hydrate the diagnostic item from the
given XML element.
|
|
/// </summary>
|
|
/// <param name="itemSpecificNode">The XML element containing the diagnostic.</param>
|
|
protected
override
void
ReadItemSpecificFields(System.Xml.Linq.XElement itemSpecificNode)
|
|
{
|
|
this.InvalidExtensionName
=
base.ReadCustomField(itemSpecificNode,
InvalidExtensionnameKey);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write the state into the given XML
element.
|
|
/// </summary>
|
|
/// <param name="itemSpecificNode">The element into which the state is persisted.</param>
|
|
protected
override
void
WriteItemSpecificFields(System.Xml.Linq.XElement itemSpecificNode)
|
|
{
|
|
this.WriteCustomField(itemSpecificNode,
InvalidExtensionnameKey, this.InvalidExtensionName);
|
|
}
|
|
}
|
|
}
|
No comments:
Post a Comment