protected void AddClassMethodCode(AxClass newAxClass) { if (String.IsNullOrEmpty(CodeGenerate.GetResult())) { return; } if (IsPreviewMode) { CodeGenerate.AppendLine(""); } else { if (CodeGenerate.MethodType == ClassMethodType.ClassDeclaration) { newAxClass.SourceCode.Declaration = CodeGenerate.GetResult(); } else { AxMethod axMethod = new AxMethod(); axMethod.Name = CodeGenerate.MethodName; axMethod.IsStatic = (CodeGenerate.MethodType == ClassMethodType.Static); axMethod.Source = CodeGenerate.GetResult(); newAxClass.AddMethod(axMethod); } CodeGenerate.ClearResult(); } }
public void applyValidateMethod(AxClass selectedClass, AxClass contractClass) { var validateMethod = selectedClass.Methods.Where(m => m.Name.Equals("Validate", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); AxMethod axValidateMethod = new AxMethod() { Name = "validate", ReturnType = new AxMethodReturnType() { Type = Microsoft.Dynamics.AX.Metadata.Core.MetaModel.CompilerBaseType.AnyType, TypeName = "boolean" } }; if (validateMethod != null) { axValidateMethod.Source = validateMethod.Source.Replace("Object calledFrom = null", ""); } else { // we need to put a dummy method here axValidateMethod.Source = @" public boolean validate(Object calledFrom = null) { boolean ret; ret = super(calledFrom); return ret; }" + Environment.NewLine; } contractClass.AddMethod(axValidateMethod); }
/// <summary> /// Adds a new method (with a hard-coded name and empty body) to the selected class. /// </summary> /// <param name="c">The class to which the method will be added.</param> /// <remarks> /// The method is added to the underlying file, but not to the designer. /// Visual Studio will detect the change and asks the user if the file should be reloaded. /// Another approach is needed to update the designer directly. /// </remarks> void AddMethodToFile(ClassItem c) { AxClass axClass = (AxClass)c.GetMetadataType(); // Add the method to the class axClass.AddMethod(BuildMethod()); // Prepare objects needed for saving var metaModelProviders = ServiceLocator.GetService(typeof(IMetaModelProviders)) as IMetaModelProviders; var metaModelService = metaModelProviders.CurrentMetaModelService; // Getting the model will likely have to be more sophisticated, such as getting the model of the project and checking // if the object has the same model. // But this shold do for demonstration. ModelInfo model = DesignMetaModelService.Instance.CurrentMetadataProvider.Classes.GetModelInfo(axClass.Name).FirstOrDefault <ModelInfo>(); // Update the file metaModelService.UpdateClass(axClass, new ModelSaveInfo(model)); }
/// <summary> /// Called when user clicks on the add-in menu /// </summary> /// <param name="e">The context of the VS tools and metadata</param> public override void OnClick(AddinDesignerEventArgs e) { try { int displayOrder = 0; // we will create Extension class here var selectedElement = e.SelectedElement as Microsoft.Dynamics.Framework.Tools.MetaModel.Automation.IRootElement; if (selectedElement != null) { // Find current model var modelSaveInfo = Common.CommonUtil.GetCurrentModelSaveInfo(); var metaModelService = Common.CommonUtil.GetModelSaveService(); IClassItem classItem = selectedElement as IClassItem; // Get the selected class AxClass object AxClass selectedClass = Common.CommonUtil.GetModelSaveService().GetClass(classItem.Name); // TODO: check that the class is a RunBaseBatch class. Otherwise send message that this is not required. // Create Contract class Microsoft.Dynamics.AX.Metadata.MetaModel.AxClass contractClass = new AxClass() { Name = classItem.Name + "Contract", }; contractClass.Implements.Add("SysOperationValidatable"); contractClass.AddAttribute(new AxAttribute() { Name = "DataContract" }); contractClass.SourceCode.Declaration = $"[DataContract]\npublic final class {contractClass.Name} implements SysOperationValidatable\n{{\n\n}}"; // this is replaced again later with the variables List <string> contractParms = new List <string>(); // store the variables here List <string> contractParmMethods = new List <string>(); // store the parm methods here List <string> axParmVariables = new List <string>(); List <AxMethod> axMethods = new List <AxMethod>(); string currentGroup = string.Empty; string headerAttributes = "DataContract"; int headerAttributeOrder = 0; var dialogMethod = selectedClass.Methods.Where(m => m.Name.Equals("dialog", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); if (dialogMethod != null) { // from the dialog method we would know what the code fields should be var dialogSource = dialogMethod.Source; // var dialogLines = dialogSource.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList(); foreach (var dialogLine in dialogLines) { if (dialogLine.Trim().StartsWith("public")) { continue; } else if (dialogLine.Contains(".addGroup(")) { // set the group name here string dialogSourceLine = dialogLine.Substring(dialogLine.IndexOf("(") + 1); dialogSourceLine = dialogSourceLine.Replace(");", "").Replace("\"", "").Trim(); string currentGrouplabel = dialogSourceLine; currentGroup = dialogSourceLine; if (currentGroup.StartsWith("@")) { // we need to get a name for this group var label = Labels.LabelHelper.FindLabelGlobally(currentGrouplabel); if (label != null) { currentGroup = label.LabelText; } } currentGroup = currentGroup.Replace(" ", "").Trim(); headerAttributes += $", SysOperationGroupAttribute('{currentGroup}', \"{currentGrouplabel}\", '{headerAttributeOrder}')"; headerAttributeOrder++; } else if (dialogLine.Contains(".addField")) { string addFieldLine = dialogLine.Trim(); // so over here we will get the field to add as a member & parm method addFieldLine = addFieldLine.Substring(addFieldLine.IndexOf(".addField")); addFieldLine = addFieldLine.Substring(addFieldLine.IndexOf("(") + 1); addFieldLine = addFieldLine.Replace(");", "").Trim(); var parameters = addFieldLine.Split(new string[] { "," }, StringSplitOptions.None).ToList(); parameters.ForEach(p => p.Trim()); string fieldType = String.Empty; string fieldLabel = String.Empty; string fieldHelp = String.Empty; string fieldName = String.Empty; string attributes = String.Empty; attributes = $"[DataMember, SysOperationDisplayOrder('{displayOrder}')"; // we will always have a fieldType (or atleast we should) fieldType = parameters[0].Substring(parameters[0].IndexOf("(") + 1) .Replace("(", "").Replace(")", "").Trim(); if (parameters.Count >= 2) { fieldName = parameters[1].Replace("\"", "").Trim(); //if (String.IsNullOrEmpty(fieldLabel) == false) //{ // attributes += $", SysOperationLabel('{fieldName}')"; //} } if (parameters.Count >= 3) { fieldLabel = parameters[2].Replace("\"", "").Trim(); if (String.IsNullOrEmpty(fieldLabel) == false) { attributes += $", SysOperationLabel(\"{fieldLabel}\")"; } } if (parameters.Count >= 4) { fieldHelp = parameters[3].Replace("\"", "").Trim(); if (String.IsNullOrEmpty(fieldHelp) == false) { attributes += $", SysOperationHelpText(\"{fieldHelp}\")"; } } // add the group here if (!String.IsNullOrEmpty(currentGroup)) { attributes += $", SysOperationGroupMemberAttribute(\"{currentGroup}\")"; } attributes += "]"; /* Crude method * string fieldType = addFieldLine.Substring(0, addFieldLine.IndexOf(",")); * fieldType = fieldType.Substring(fieldType.IndexOf("(") + 1) * .Replace("(", "").Replace(")", "").Trim(); * * string fieldLabel = String.Empty; * string fieldHelp = String.Empty; * string fieldName = addFieldLine.Substring(addFieldLine.IndexOf(",") + 1) * .Replace(")", "").Replace(";", "").Trim(); * if (fieldName.Count(c => c == ',') > 0) * { * // that means there is a label / help label in here as well * // Break the fieldname further * // find the label here * string fieldNameLabel = fieldName; * fieldName = fieldNameLabel.Substring(0, fieldNameLabel.IndexOf(",")).Trim(); * * // find the help label here * } */ AxClassMemberVariable axVar = new AxClassMemberVariable { TypeName = fieldType, Name = fieldName }; axVar.Type = Microsoft.Dynamics.AX.Metadata.Core.MetaModel.CompilerBaseType.AnyType; axParmVariables.Add($"\t{fieldType} {fieldName};"); contractClass.AddMember(axVar); // need to add Attributes here // add parameters to the method //fieldName = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(fieldName); AxMethod method = new AxMethod { Name = "parm" + System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(fieldName), ReturnType = new AxMethodReturnType() { TypeName = fieldType } }; //,{SysOperationLabelAttribute(""{}"")} // add the group & label & help attribute method.Source = //$@" [DataMember,SysOperationDisplayOrder('{displayOrder}')] $@" {attributes} public {fieldType} {method.Name} ({fieldType} _{fieldName} = {fieldName}) {{ {fieldName} = _{fieldName}; return {fieldName}; }}" + Environment.NewLine; //contractClass.AddMethod(method); axMethods.Add(method); displayOrder++; } } } // Add all the axmethods here string parmVarSource = string.Empty; axParmVariables.ForEach(s => parmVarSource = parmVarSource + "\n" + s); //contractClass.SourceCode.Declaration = $"[DataContract]\npublic final class {contractClass.Name}\n{{\n{parmVarSource}\n\n}}"; contractClass.SourceCode.Declaration = $"[{headerAttributes}]\npublic final class {contractClass.Name} implements SysOperationValidatable\n{{\n{parmVarSource}\n\n}}"; axMethods.ForEach(method => contractClass.AddMethod(method)); // Create validate method this.applyValidateMethod(selectedClass, contractClass); metaModelService.CreateClass(contractClass, modelSaveInfo); Common.CommonUtil.AddElementToProject(contractClass); //extensionClass.SourceCode.Declaration = $"[ExtensionOf({intrinsicStr}({selectedElement.Name}))]\npublic final class {className}\n{{\n\n}}"; /* * * metaModelService.CreateClass(extensionClass, modelSaveInfo); * Common.CommonUtil.AddElementToProject(extensionClass); */ } } catch (Exception ex) { CoreUtility.HandleExceptionWithErrorMessage(ex); } }