using System; using System.Linq; using System.Threading.Tasks; using CTA.WebForms.Services; using CTA.WebForms.TagCodeBehindHandlers; using HtmlAgilityPack; namespace CTA.WebForms.TagConverters { /// /// An abstract converter capable of porting view layer tags of a given /// type to an alternate representation. This includes porting related /// to code behind references. /// public abstract class TagConverter { private protected TaskManagerService _taskManagerService; private protected CodeBehindReferenceLinkerService _codeBehindLinkerService; private protected ViewImportService _viewImportService; /// /// The name of the tag to apply this converter to. /// public string TagName { get; set; } /// /// The type representation of the source tag in code behind /// files, if such a type exists. /// public string CodeBehindType { get; set; } /// /// The name of the type to be used for conversion of code behind /// references to the source tag. In most cases /// will be sufficient. /// public string CodeBehindHandler { get; set; } /// /// The set of conditions used to decide which template to use on any /// given source tag. /// /// /// Used to inject any necessary services and perform other initialization /// steps required before tag migration. /// /// The service instance that is used /// to perform managed calls to other services. /// The service instance that will /// be used to convert tag code behind references. /// The service instance that will be used /// for adding any view imports needed for the conversion. public virtual void Initialize( TaskManagerService taskManagerService, CodeBehindReferenceLinkerService codeBehindLinkerService, ViewImportService viewImportService) { _taskManagerService = taskManagerService; _codeBehindLinkerService = codeBehindLinkerService; _viewImportService = viewImportService; } /// /// Retrieves an instance of the specified code behind handler class /// if one exists. /// /// The value of the ID attribute for the node which this /// handler will be used on. /// An instance of the converter's code behind handler class if /// one was specified, otherwise null. /// Throws if code behind handler /// is specified but class couldn't be found. public TagCodeBehindHandler GetCodeBehindHandlerInstance(string idValue) { if (CodeBehindHandler == null || string.IsNullOrWhiteSpace(idValue)) { return null; } var handlerType = GetCodeBehindHandlerType(); if (handlerType == null) { throw new InvalidOperationException($"Code behind handler type {CodeBehindHandler} could not be found"); } return (TagCodeBehindHandler)Activator.CreateInstance(handlerType, CodeBehindType, idValue); } /// /// Retrieves the type of the specified code behind handler class /// if one exists. /// /// The code behind handler type if it can be found, null otherwise private protected Type GetCodeBehindHandlerType() { if (CodeBehindHandler == null) { return null; } var handlerClassName = CodeBehindHandler.Equals("Default", StringComparison.InvariantCultureIgnoreCase) ? nameof(DefaultTagCodeBehindHandler) : CodeBehindHandler; var webFormsAssembly = AppDomain.CurrentDomain .GetAssemblies() .Where(a => a.FullName.StartsWith("CTA.WebForms") && !a.FullName.Contains("Test")) .FirstOrDefault(); var handlerType = webFormsAssembly? .GetTypes() .Where(t => t.Name.Equals(handlerClassName) && !t.IsAbstract && !t.IsInterface) .FirstOrDefault(); return handlerType; } /// /// Replaces the provided with its Blazor equivalent /// as specified by the given converter. /// /// The tag to be replaced. /// The path of the view file being modified. /// The code behind handler to be used on this node, if one exists. /// The task id of the view file converter that called this method. public abstract Task MigrateTagAsync(HtmlNode node, string viewFilePath, TagCodeBehindHandler handler, int taskId); /// /// Checks whether the properties of this converter form a valid configuration. /// public abstract void Validate(); } }