private static string getHandlerMatchExpression( WebItemGeneralData generalData, IReadOnlyCollection <WebItemParameter> requiredParameters, bool compareEntitySetup) => (compareEntitySetup ? "r.EsAsBaseType is {0} match".FormatWith(generalData.ClassName) : "urlHandler is {0} match".FormatWith(generalData.ClassName)) + StringTools.ConcatenateWithDelimiter( " && ", requiredParameters.Select(i => i.GetEqualityExpression("match.{0}".FormatWith(i.PropertyName), i.PropertyName))) .PrependDelimiter(" && ");
internal static void WriteConstructorAndHelperMethods( TextWriter writer, WebItemGeneralData generalData, IReadOnlyCollection <WebItemParameter> requiredParameters, IReadOnlyCollection <WebItemParameter> optionalParameters, bool includeEsParameter, bool isEs) { // It's important to force the cache to be enabled in the constructor since these objects are often created in post-back-action getters. writeConstructorDocComments(writer, requiredParameters); var constructorParameters = "( " + StringTools.ConcatenateWithDelimiter( ", ", includeEsParameter ? "EntitySetup es" : "", WebFrameworkStatics.GetParameterDeclarations(requiredParameters), optionalParameters.Count > 0 ? "Action<{0}> optionalParameterSetter = null".FormatWith( StringTools.ConcatenateWithDelimiter( ", ", "OptionalParameterSpecifier", includeEsParameter ? "EntitySetup" : "", "Parameters")) : "", !isEs ? "string uriFragmentIdentifier = \"\"" : "") + " ) {"; writer.WriteLine("internal {0}".FormatWith(generalData.ClassName) + constructorParameters); writer.WriteLine("DataAccessState.Current.ExecuteWithCache( () => {"); // Initialize parameter fields. We want to create and call this method even if there are no parameters so that non-generated constructors can still call // it and remain resistant to changes. writer.WriteLine( "initParameters( " + StringTools.ConcatenateWithDelimiter( ", ", includeEsParameter ? "es" : "", GetInfoConstructorArgumentsForRequiredParameters(requiredParameters, p => p.Name), optionalParameters.Count > 0 ? "optionalParameterSetter: optionalParameterSetter" : "", !isEs ? "uriFragmentIdentifier: uriFragmentIdentifier" : "") + " );"); // Call init. writer.WriteLine("init();"); writer.WriteLine("} );"); if (generalData.IsResource() && optionalParameters.Any()) { writer.WriteLine( "segmentParameterSpecifier = new Lazy<SegmentParameterSpecifier>( () => { var specifier = new SegmentParameterSpecifier(); specifySegmentParameters( specifier ); return specifier; }, LazyThreadSafetyMode.None );"); } writer.WriteLine("}"); writeInitParametersMethod(writer, generalData, requiredParameters, optionalParameters, includeEsParameter, isEs, constructorParameters); }
private static void generateForFolder( TextWriter writer, string projectPath, string projectNamespace, bool projectContainsFramework, ImmutableHashSet <string> ignoredFolderPaths, string staticFilesFolderPath, string staticFilesFolderUrlParentExpression, string folderPathRelativeToProject) { if (ignoredFolderPaths.Contains(folderPathRelativeToProject)) { return; } if (folderPathRelativeToProject == staticFilesFolderPath) { generateStaticFileLogic( writer, projectPath, projectNamespace, projectContainsFramework, null, folderPathRelativeToProject, staticFilesFolderUrlParentExpression); return; } var folderPath = EwlStatics.CombinePaths(projectPath, folderPathRelativeToProject); // Generate code for the entity setup if one exists in this folder. var entitySetupFileName = ""; foreach (var fileName in new[] { "EntitySetup.cs" }) { if (File.Exists(EwlStatics.CombinePaths(folderPath, fileName))) { entitySetupFileName = fileName; break; } } EntitySetup entitySetup = null; if (entitySetupFileName.Length > 0) { var filePathRelativeToProject = Path.Combine(folderPathRelativeToProject, entitySetupFileName); entitySetup = new EntitySetup(projectContainsFramework, new WebItemGeneralData(projectPath, projectNamespace, filePathRelativeToProject, false)); entitySetup.GenerateCode(writer); } if (legacyUrlStatics != null) { var files = new List <WebItemGeneralData>(); foreach (var fileName in IoMethods.GetFileNamesInFolder(folderPath, searchPattern: "*.aspx").OrderBy(i => i)) { var filePath = EwlStatics.CombinePaths(projectPath, folderPathRelativeToProject, fileName); var aspxLines = File.ReadAllLines(filePath); if (aspxLines.Length != 1 || !Regex.IsMatch(aspxLines[0], "^<%@ .+ %>$")) { throw new Exception("Invalid ASPX file: \"{0}\"".FormatWith(EwlStatics.CombinePaths(folderPathRelativeToProject, fileName))); } var newCsLines = new List <string>(); var pageNeeded = true; foreach (var line in File.ReadAllLines(EwlStatics.CombinePaths(projectPath, folderPathRelativeToProject, fileName + ".cs"))) { if (pageNeeded && !line.StartsWith("using ")) { newCsLines.Add(""); newCsLines.Add("// EwlPage"); pageNeeded = false; } newCsLines.Add(line.Replace(": EwfPage {", " {").Replace(": EwfPage,", ":")); } var newCsFilePath = EwlStatics.CombinePaths(folderPathRelativeToProject, Path.GetFileNameWithoutExtension(fileName) + ".cs"); File.WriteAllText( EwlStatics.CombinePaths(projectPath, newCsFilePath), newCsLines.Aggregate((text, line) => text + Environment.NewLine + line), Encoding.UTF8); files.Add(new WebItemGeneralData(projectPath, projectNamespace, newCsFilePath, false)); aspxFilePaths.Add(filePath); aspxFilePaths.Add(filePath + ".cs"); aspxFilePaths.Add(filePath + ".designer.cs"); } const string folderSetupClassName = "LegacyUrlFolderSetup"; var childPatterns = files.Select( file => "new UrlPattern( encoder => encoder is {0}.UrlEncoder ? EncodingUrlSegment.Create( {1} ) : null, url => string.Equals( url.Segment, {1}, StringComparison.OrdinalIgnoreCase ) ? new {0}.UrlDecoder() : null )" .FormatWith(file.ClassName, "\"{0}.aspx\"".FormatWith(Path.GetFileNameWithoutExtension(file.FileName)))) .Concat( IoMethods.GetFolderNamesInFolder(folderPath) .Where( subfolderName => { var subfolderPath = EwlStatics.CombinePaths(folderPathRelativeToProject, subfolderName); if (subfolderPath == "bin" || subfolderPath == "obj") { return(false); } bool folderContainsAspxFiles(string path) => IoMethods.GetFileNamesInFolder(path, searchPattern: "*.aspx").Any() || IoMethods.GetFolderNamesInFolder(path) .Any(i => folderContainsAspxFiles(EwlStatics.CombinePaths(path, i))); return(folderContainsAspxFiles(EwlStatics.CombinePaths(projectPath, subfolderPath))); }) .Select( subfolderName => "{0}.{1}.UrlPatterns.Literal( \"{2}\" )".FormatWith( WebItemGeneralData.GetNamespaceFromPath(projectNamespace, EwlStatics.CombinePaths(folderPathRelativeToProject, subfolderName), false) .Separate(".", false) .Last(), folderSetupClassName, subfolderName))) .Materialize(); if (folderPathRelativeToProject.Length == 0) { legacyUrlStatics.AppendLine("using System;"); legacyUrlStatics.AppendLine("using System.Collections.Generic;"); legacyUrlStatics.AppendLine("using EnterpriseWebLibrary.EnterpriseWebFramework;"); legacyUrlStatics.AppendLine(); legacyUrlStatics.AppendLine("namespace {0} {{".FormatWith(projectNamespace)); legacyUrlStatics.AppendLine("internal static class LegacyUrlStatics {"); legacyUrlStatics.AppendLine("public static IReadOnlyCollection<UrlPattern> GetPatterns() {"); legacyUrlStatics.AppendLine("var patterns = new List<UrlPattern>();"); foreach (var i in childPatterns) { legacyUrlStatics.AppendLine("patterns.Add( {0} );".FormatWith(i)); } legacyUrlStatics.AppendLine("return patterns;"); legacyUrlStatics.AppendLine("}"); legacyUrlStatics.AppendLine("public static UrlHandler GetParent() => new YourRootHandler();"); legacyUrlStatics.AppendLine("}"); legacyUrlStatics.Append("}"); } else if (childPatterns.Any()) { var folderSetup = new StringBuilder(); folderSetup.AppendLine("using System;"); folderSetup.AppendLine("using System.Collections.Generic;"); folderSetup.AppendLine("using EnterpriseWebLibrary.EnterpriseWebFramework;"); folderSetup.AppendLine(); folderSetup.AppendLine("// EwlResource"); folderSetup.AppendLine(); var folderNamespace = WebItemGeneralData.GetNamespaceFromPath(projectNamespace, folderPathRelativeToProject, false); folderSetup.AppendLine("namespace {0} {{".FormatWith(folderNamespace)); folderSetup.AppendLine("partial class {0} {{".FormatWith(folderSetupClassName)); var namespaces = folderNamespace.Substring(projectNamespace.Length + ".".Length).Separate(".", false); folderSetup.AppendLine( "protected override UrlHandler getUrlParent() => {0};".FormatWith( namespaces.Count == 1 ? "LegacyUrlStatics.GetParent()" : "new {0}.{1}()".FormatWith(namespaces[namespaces.Count - 2], folderSetupClassName))); folderSetup.AppendLine("protected override ConnectionSecurity ConnectionSecurity => ConnectionSecurity.MatchingCurrentRequest;"); folderSetup.AppendLine("protected override IEnumerable<UrlPattern> getChildUrlPatterns() {"); folderSetup.AppendLine("var patterns = new List<UrlPattern>();"); foreach (var i in childPatterns) { folderSetup.AppendLine("patterns.Add( {0} );".FormatWith(i)); } folderSetup.AppendLine("return patterns;"); folderSetup.AppendLine("}"); folderSetup.AppendLine("}"); folderSetup.Append("}"); Directory.CreateDirectory(EwlStatics.CombinePaths(projectPath, folderPathRelativeToProject, "Legacy URLs")); File.WriteAllText( EwlStatics.CombinePaths(projectPath, folderPathRelativeToProject, "Legacy URLs", "{0}.cs".FormatWith(folderSetupClassName)), folderSetup.ToString(), Encoding.UTF8); } foreach (var file in files) { var parentCode = new StringBuilder(); parentCode.AppendLine(); parentCode.AppendLine(); parentCode.AppendLine("namespace {0} {{".FormatWith(file.Namespace)); parentCode.AppendLine("partial class {0} {{".FormatWith(file.ClassName)); parentCode.AppendLine( "protected override UrlHandler getUrlParent() => {0};".FormatWith( folderPathRelativeToProject.Length == 0 ? "LegacyUrlStatics.GetParent()" : "new {0}()".FormatWith(folderSetupClassName))); parentCode.AppendLine("}"); parentCode.Append("}"); File.AppendAllText(EwlStatics.CombinePaths(projectPath, file.PathRelativeToProject), parentCode.ToString(), Encoding.UTF8); } } // Generate code for files in the current folder. foreach (var fileName in IoMethods.GetFileNamesInFolder(folderPath)) { if (legacyUrlStatics != null && aspxFilePaths.Any(i => i.EqualsIgnoreCase(EwlStatics.CombinePaths(projectPath, folderPathRelativeToProject, fileName)))) { continue; } if (Path.GetExtension(fileName).ToLowerInvariant() != ".cs") { continue; } var generalData = new WebItemGeneralData(projectPath, projectNamespace, EwlStatics.CombinePaths(folderPathRelativeToProject, fileName), false); if (!generalData.IsResource()) { continue; } new Resource(projectContainsFramework, generalData, entitySetup).GenerateCode(writer); } // Delve into sub folders. foreach (var subFolderName in IoMethods.GetFolderNamesInFolder(folderPath)) { var subFolderPath = Path.Combine(folderPathRelativeToProject, subFolderName); if (subFolderPath == "bin" || subFolderPath == "obj") { continue; } generateForFolder( writer, projectPath, projectNamespace, projectContainsFramework, ignoredFolderPaths, staticFilesFolderPath, staticFilesFolderUrlParentExpression, subFolderPath); } }
private static void writeInitParametersMethod( TextWriter writer, WebItemGeneralData generalData, IReadOnlyCollection <WebItemParameter> requiredParameters, IReadOnlyCollection <WebItemParameter> optionalParameters, bool includeEsParameter, bool isEs, string constructorParameters) { CodeGenerationStatics.AddSummaryDocComment( writer, "Initializes required and optional parameters. A call to this should be the first line of every non-generated constructor."); writer.WriteLine("private void initParameters" + constructorParameters); if (includeEsParameter) { writer.WriteLine("Es = es;"); } foreach (var requiredParameter in requiredParameters) { if (requiredParameter.IsString || requiredParameter.IsEnumerable) { writer.WriteLine( "if( " + requiredParameter.Name + " == null ) throw new ApplicationException( \"You cannot specify null for the value of a string or an IEnumerable.\" );"); } writer.WriteLine(requiredParameter.FieldName + " = " + requiredParameter.Name + ";"); } // Initialize optional parameter fields. if (optionalParameters.Any()) { writer.WriteLine("var optionalParametersInitializedFromCurrent = false;"); writer.WriteLine("if( EwfApp.Instance != null && AppRequestState.Instance != null ) {"); // If the list of current URL handlers has a matching object, apply its parameter values. writer.WriteLine("foreach( var urlHandler in AppRequestState.Instance.UrlHandlers )"); if (isEs) { writer.WriteLine("if( urlHandler is ResourceBase r ) {"); writer.WriteLine("if( {0} ) {{".FormatWith(getHandlerMatchExpression(generalData, requiredParameters, true))); generateMatchingHandlerParameterInitStatements(writer, optionalParameters, false); writer.WriteLine("}"); writer.WriteLine("}"); writer.WriteLine("else {"); writer.WriteLine("if( {0} ) {{".FormatWith(getHandlerMatchExpression(generalData, requiredParameters, false))); generateMatchingHandlerParameterInitStatements(writer, optionalParameters, false); writer.WriteLine("}"); writer.WriteLine("}"); } else { writer.WriteLine("if( {0} ) {{".FormatWith(getHandlerMatchExpression(generalData, requiredParameters, false))); generateMatchingHandlerParameterInitStatements(writer, optionalParameters, false); writer.WriteLine("}"); } // If new parameter values are effective, and the current resource or an ancestor matches this object, apply its new parameter values. if (generalData.IsPage() || isEs) { writer.WriteLine("if( AppRequestState.Instance.NewUrlParameterValuesEffective ) {"); writer.WriteLine("UrlHandler urlHandler = {0}Current;".FormatWith(generalData.IsPage() ? "" : "PageBase.")); writer.WriteLine("do"); if (isEs) { writer.WriteLine("if( urlHandler is ResourceBase r ) {"); writer.WriteLine("if( {0} ) {{".FormatWith(getHandlerMatchExpression(generalData, requiredParameters, true))); generateMatchingHandlerParameterInitStatements(writer, optionalParameters, true); writer.WriteLine("}"); writer.WriteLine("}"); writer.WriteLine("else {"); writer.WriteLine("if( {0} ) {{".FormatWith(getHandlerMatchExpression(generalData, requiredParameters, false))); generateMatchingHandlerParameterInitStatements(writer, optionalParameters, true); writer.WriteLine("}"); writer.WriteLine("}"); } else { writer.WriteLine("if( {0} ) {{".FormatWith(getHandlerMatchExpression(generalData, requiredParameters, false))); generateMatchingHandlerParameterInitStatements(writer, optionalParameters, true); writer.WriteLine("}"); } writer.WriteLine("while( ( urlHandler = urlHandler.GetParent() ) != null );"); writer.WriteLine("}"); } writer.WriteLine("}"); // Apply parameter values from the setter. writer.WriteLine("var optionalParameterSpecifier = new OptionalParameterSpecifier();"); writer.WriteLine( "optionalParameterSetter?.Invoke( {0} );".FormatWith( StringTools.ConcatenateWithDelimiter( ", ", "optionalParameterSpecifier", includeEsParameter ? "es" : "", "new Parameters( {0} )".FormatWith( StringTools.ConcatenateWithDelimiter( ", ", requiredParameters.Select(i => i.PropertyName) .Append( "optionalParametersInitializedFromCurrent ? new OptionalParameters( {0} ) : null".FormatWith( StringTools.ConcatenateWithDelimiter(", ", optionalParameters.Select(i => i.PropertyName))))))))); foreach (var i in optionalParameters) { writer.WriteLine( "if( optionalParameterSpecifier.{0} ) {1} = optionalParameterSpecifier.{2};".FormatWith( OptionalParameterPackageStatics.GetWasSpecifiedPropertyName(i), i.FieldName, i.PropertyName)); } // This is called after all current values and values from the setter have been incorporated since these can affect default values. writer.WriteLine( "specifyParameterDefaults( {0} );".FormatWith( StringTools.ConcatenateWithDelimiter( ", ", WebItemGeneralData.ParameterDefaultsFieldName, includeEsParameter ? "es" : "", "new Parameters( {0} )".FormatWith( StringTools.ConcatenateWithDelimiter( ", ", requiredParameters.Select(i => i.PropertyName) .Append( "new OptionalParameters( {0} )".FormatWith( StringTools.ConcatenateWithDelimiter(", ", optionalParameters.Select(i => i.PropertyName))))))))); // Apply default values to parameters not yet initialized. writer.WriteLine("if( !optionalParametersInitializedFromCurrent ) {"); foreach (var i in optionalParameters) { writer.WriteLine( "if( !optionalParameterSpecifier.{0} && {1}.{0} ) {2} = {1}.{3};".FormatWith( OptionalParameterPackageStatics.GetWasSpecifiedPropertyName(i), WebItemGeneralData.ParameterDefaultsFieldName, i.FieldName, i.PropertyName)); } writer.WriteLine("}"); } if (!isEs) { writer.WriteLine("base.uriFragmentIdentifier = uriFragmentIdentifier;"); } if (optionalParameters.Any()) { writer.WriteLine("this.optionalParameterSetter = optionalParameterSetter;"); } writer.WriteLine("}"); // initParameters method }
private static void generateStaticFileLogic( TextWriter writer, string projectPath, string projectNamespace, bool inFramework, bool?inVersionedFolder, string folderPathRelativeToProject, string folderParentExpression) { var isRootFolder = !inVersionedFolder.HasValue; var folderPath = EwlStatics.CombinePaths(projectPath, folderPathRelativeToProject); var folderNamespace = WebItemGeneralData.GetNamespaceFromPath(projectNamespace, folderPathRelativeToProject, false); const string folderSetupClassName = "FolderSetup"; var files = IoMethods.GetFileNamesInFolder(folderPath) .Select(i => new WebItemGeneralData(projectPath, projectNamespace, EwlStatics.CombinePaths(folderPathRelativeToProject, i), true)) .Materialize(); var subfolderNames = IoMethods.GetFolderNamesInFolder(folderPath) .Where(i => !isRootFolder || i != AppStatics.StaticFileLogicFolderName) .Materialize(); generateStaticFileFolderSetup( writer, inFramework, isRootFolder, folderPathRelativeToProject, folderNamespace, folderSetupClassName, folderParentExpression, files.Select(i => "{0}.UrlPatterns.Literal( \"{1}\" )".FormatWith(i.ClassName, i.FileName)) .Concat( subfolderNames.Select( subfolderName => "{0}.{1}.UrlPatterns.Literal( \"{2}\" )".FormatWith( WebItemGeneralData.GetNamespaceFromPath(projectNamespace, EwlStatics.CombinePaths(folderPathRelativeToProject, subfolderName), false) .Separate(".", false) .Last(), folderSetupClassName, subfolderName))) .Materialize()); foreach (var file in files) { new StaticFile(file, inFramework, inVersionedFolder == true, folderSetupClassName).GenerateCode(writer); } var staticFilesFolderPath = inFramework ? EnterpriseWebFramework.StaticFile.FrameworkStaticFilesSourceFolderPath : EnterpriseWebFramework.StaticFile.AppStaticFilesFolderName; var logicFolderPath = EwlStatics.CombinePaths( projectPath, staticFilesFolderPath, AppStatics.StaticFileLogicFolderName, folderPathRelativeToProject.Substring((staticFilesFolderPath + (isRootFolder ? "" : Path.DirectorySeparatorChar.ToString())).Length)); Directory.CreateDirectory(logicFolderPath); createStaticFileLogicTemplate(logicFolderPath, folderNamespace, folderSetupClassName); foreach (var i in files) { createStaticFileLogicTemplate(logicFolderPath, i.Namespace, i.ClassName); } foreach (var subfolderName in subfolderNames) { generateStaticFileLogic( writer, projectPath, projectNamespace, inFramework, inVersionedFolder ?? subfolderName == "versioned", EwlStatics.CombinePaths(folderPathRelativeToProject, subfolderName), "new {0}.{1}()".FormatWith(folderNamespace.Separate(".", false).Last(), folderSetupClassName)); } }