protected internal override void ProcessExternalResource( IResourceBuildHelper helper, string url, out string preProcessed, out string compacted, List <ParseException> errors) { compacted = preProcessed = String.Empty; Uri uri; if (!Uri.TryCreate(url, UriKind.Absolute, out uri)) { throw new ArgumentException("Invalid external URL"); } string ext = Path.GetExtension(uri.AbsolutePath).Trim('.'); CompilerType compiler = helper.GetDefaultCompilerTypeForLanguage(ext); if (!typeof(ResourceCodeProvider).IsAssignableFrom(compiler.CodeDomProviderType)) { // don't know how to process any further return; } ResourceCodeProvider provider = (ResourceCodeProvider)Activator.CreateInstance(compiler.CodeDomProviderType); try { // concatenate the preprocessed source for current merge phase provider.ProcessExternalResource( helper, url, out preProcessed, out compacted, errors); } catch (ParseException ex) { errors.Add(ex); } catch (Exception ex) { errors.Add(new ParseError(ex.Message, url, 0, 0, ex)); } if (!this.isMimeSet && !String.IsNullOrEmpty(provider.ContentType) && !String.IsNullOrEmpty(provider.FileExtension)) { this.contentType = provider.ContentType; this.fileExtension = provider.FileExtension; this.isMimeSet = true; } }
public override void GenerateCode(AssemblyBuilder assemblyBuilder) { string contentType, fileExtension; string originalSource, prettyPrintResource, compactedResource; ResourceCodeProvider provider = assemblyBuilder.CodeDomProvider as ResourceCodeProvider; if (provider != null) { originalSource = provider.CompileResource( this, base.VirtualPath, out prettyPrintResource, out compactedResource); contentType = provider.ContentType; fileExtension = provider.FileExtension; } else { // read the resource contents using (TextReader reader = this.OpenReader()) { originalSource = compactedResource = prettyPrintResource = reader.ReadToEnd(); } contentType = "text/plain"; fileExtension = "txt"; } IResourceNameGenerator nameGenerator = assemblyBuilder.CodeDomProvider as IResourceNameGenerator; if (nameGenerator != null) { this.ResourceFullName = nameGenerator.GenerateResourceName(base.VirtualPath); } else { this.ResourceFullName = ResourceBuildProvider.GenerateTypeNameFromPath(base.VirtualPath); } byte[] gzippedBytes, deflatedBytes; ResourceBuildProvider.Compress(compactedResource, out gzippedBytes, out deflatedBytes); string hash = ResourceBuildProvider.ComputeHash(compactedResource); // generate a resource container CodeCompileUnit generatedUnit = new CodeCompileUnit(); #region namespace ResourceNamespace CodeNamespace ns = new CodeNamespace(this.ResourceNamespace); generatedUnit.Namespaces.Add(ns); #endregion namespace ResourceNamespace #region public sealed class ResourceTypeName CodeTypeDeclaration resourceType = new CodeTypeDeclaration(); resourceType.IsClass = true; resourceType.Name = this.ResourceTypeName; resourceType.Attributes = MemberAttributes.Public | MemberAttributes.Final; provider.SetBaseClass(resourceType); resourceType.BaseTypes.Add(typeof(IOptimizedResult)); ns.Types.Add(resourceType); #endregion public sealed class ResourceTypeName #region [BuildPath(virtualPath)] string virtualPath = base.VirtualPath; if (HttpRuntime.AppDomainAppVirtualPath.Length > 1) { virtualPath = virtualPath.Substring(HttpRuntime.AppDomainAppVirtualPath.Length); } virtualPath = "~" + virtualPath; CodeAttributeDeclaration attribute = new CodeAttributeDeclaration( new CodeTypeReference(typeof(BuildPathAttribute)), new CodeAttributeArgument(new CodePrimitiveExpression(virtualPath))); resourceType.CustomAttributes.Add(attribute); #endregion [BuildPath(virtualPath)] #region private static readonly byte[] GzippedBytes CodeMemberField field = new CodeMemberField(); field.Name = "GzippedBytes"; field.Type = new CodeTypeReference(typeof(byte[])); field.Attributes = MemberAttributes.Private | MemberAttributes.Static | MemberAttributes.Final; CodeArrayCreateExpression arrayInit = new CodeArrayCreateExpression(field.Type, gzippedBytes.Length); foreach (byte b in gzippedBytes) { arrayInit.Initializers.Add(new CodePrimitiveExpression(b)); } field.InitExpression = arrayInit; resourceType.Members.Add(field); #endregion private static static readonly byte[] GzippedBytes #region private static readonly byte[] DeflatedBytes; field = new CodeMemberField(); field.Name = "DeflatedBytes"; field.Type = new CodeTypeReference(typeof(byte[])); field.Attributes = MemberAttributes.Private | MemberAttributes.Static | MemberAttributes.Final; arrayInit = new CodeArrayCreateExpression(field.Type, deflatedBytes.Length); foreach (byte b in deflatedBytes) { arrayInit.Initializers.Add(new CodePrimitiveExpression(b)); } field.InitExpression = arrayInit; resourceType.Members.Add(field); #endregion private static readonly byte[] DeflatedBytes; #region string IOptimizedResult.Source { get; } // add a readonly property with the original resource source CodeMemberProperty property = new CodeMemberProperty(); property.Name = "Source"; property.Type = new CodeTypeReference(typeof(String)); property.PrivateImplementationType = new CodeTypeReference(typeof(IOptimizedResult)); property.HasGet = true; // get { return originalSource; } if (originalSource == null || originalSource.Length <= 0x5DC) { property.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(originalSource))); } else { string escaped = ResourceBuildProvider.QuoteSnippetStringCStyle(originalSource); property.GetStatements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression(escaped))); } resourceType.Members.Add(property); #endregion string IOptimizedResult.Source { get; } #region string IOptimizedResult.PrettyPrinted { get; } // add a readonly property with the resource data property = new CodeMemberProperty(); property.Name = "PrettyPrinted"; property.Type = new CodeTypeReference(typeof(String)); property.PrivateImplementationType = new CodeTypeReference(typeof(IOptimizedResult)); property.HasGet = true; if (String.Equals(originalSource, prettyPrintResource)) { // get { return ((IOptimizedResult)this).Source; } CodeExpression thisRef = new CodeCastExpression(typeof(IOptimizedResult), new CodeThisReferenceExpression()); CodePropertyReferenceExpression sourceProperty = new CodePropertyReferenceExpression(thisRef, "Source"); property.GetStatements.Add(new CodeMethodReturnStatement(sourceProperty)); } else { // get { return prettyPrintResource; } if (prettyPrintResource == null || prettyPrintResource.Length <= 0x5DC) { property.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(prettyPrintResource))); } else { string escaped = ResourceBuildProvider.QuoteSnippetStringCStyle(prettyPrintResource); property.GetStatements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression(escaped))); } } resourceType.Members.Add(property); #endregion string IOptimizedResult.PrettyPrinted { get; } #region string IOptimizedResult.Compacted { get; } // add a readonly property with the compacted resource data property = new CodeMemberProperty(); property.Name = "Compacted"; property.Type = new CodeTypeReference(typeof(String)); property.PrivateImplementationType = new CodeTypeReference(typeof(IOptimizedResult)); property.HasGet = true; // get { return compactedResource; } if (compactedResource == null || compactedResource.Length <= 0x5DC) { property.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(compactedResource))); } else { string escaped = ResourceBuildProvider.QuoteSnippetStringCStyle(compactedResource); property.GetStatements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression(escaped))); } resourceType.Members.Add(property); #endregion string IOptimizedResult.Compacted { get; } #region byte[] IOptimizedResult.Gzipped { get; } // add a readonly property with the gzipped resource data property = new CodeMemberProperty(); property.Name = "Gzipped"; property.Type = new CodeTypeReference(typeof(byte[])); property.PrivateImplementationType = new CodeTypeReference(typeof(IOptimizedResult)); property.HasGet = true; // get { return GzippedBytes; } property.GetStatements.Add(new CodeMethodReturnStatement( new CodeFieldReferenceExpression( new CodeTypeReferenceExpression(this.ResourceTypeName), "GzippedBytes"))); resourceType.Members.Add(property); #endregion byte[] IOptimizedResult.Gzipped { get; } #region byte[] IOptimizedResult.Deflated { get; } // add a readonly property with the deflated resource data property = new CodeMemberProperty(); property.Name = "Deflated"; property.Type = new CodeTypeReference(typeof(byte[])); property.PrivateImplementationType = new CodeTypeReference(typeof(IOptimizedResult)); property.HasGet = true; // get { return DeflatedBytes; } property.GetStatements.Add(new CodeMethodReturnStatement( new CodeFieldReferenceExpression( new CodeTypeReferenceExpression(this.ResourceTypeName), "DeflatedBytes"))); resourceType.Members.Add(property); #endregion byte[] IOptimizedResult.Deflated { get; } #region string IBuildResultMeta.ContentType { get; } // add a readonly property with the MIME type property = new CodeMemberProperty(); property.Name = "ContentType"; property.Type = new CodeTypeReference(typeof(String)); property.PrivateImplementationType = new CodeTypeReference(typeof(IBuildResult)); property.HasGet = true; // get { return contentType; } property.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(contentType))); resourceType.Members.Add(property); #endregion string IBuildResultMeta.ContentType { get; } #region string IBuildResultMeta.FileExtension { get; } // add a readonly property with the MIME type property = new CodeMemberProperty(); property.Name = "FileExtension"; property.Type = new CodeTypeReference(typeof(String)); property.PrivateImplementationType = new CodeTypeReference(typeof(IBuildResult)); property.HasGet = true; // get { return fileExtension; } property.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(fileExtension))); resourceType.Members.Add(property); #endregion string IBuildResultMeta.FileExtension { get; } #region string IBuildResultMeta.Hash { get; } // add a readonly property with the resource data property = new CodeMemberProperty(); property.Name = "Hash"; property.Type = new CodeTypeReference(typeof(String)); property.PrivateImplementationType = new CodeTypeReference(typeof(IBuildResult)); property.HasGet = true; // get { return hash); } property.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(hash))); resourceType.Members.Add(property); #endregion string IBuildResultMeta.Hash { get; } if (this.VirtualPathDependencies.Count > 0) { resourceType.BaseTypes.Add(typeof(IDependentResult)); #region private static readonly string[] Dependencies field = new CodeMemberField(); field.Name = "Dependencies"; field.Type = new CodeTypeReference(typeof(string[])); field.Attributes = MemberAttributes.Private | MemberAttributes.Static | MemberAttributes.Final; arrayInit = new CodeArrayCreateExpression(field.Type, this.VirtualPathDependencies.Count); foreach (string key in this.VirtualPathDependencies) { arrayInit.Initializers.Add(new CodePrimitiveExpression(key)); } field.InitExpression = arrayInit; resourceType.Members.Add(field); #endregion private static readonly string[] Dependencies #region IEnumerable<string> IDependentResult.VirtualPathDependencies { get; } // add a readonly property returning the static data property = new CodeMemberProperty(); property.Name = "VirtualPathDependencies"; property.Type = new CodeTypeReference(typeof(IEnumerable <string>)); property.PrivateImplementationType = new CodeTypeReference(typeof(IDependentResult)); property.HasGet = true; // get { return Dependencies; } property.GetStatements.Add(new CodeMethodReturnStatement( new CodeFieldReferenceExpression( new CodeTypeReferenceExpression(resourceType.Name), "Dependencies"))); resourceType.Members.Add(property); #endregion IEnumerable<string> IDependentResult.VirtualPathDependencies { get; } } // allow the code provider to extend with additional properties provider.GenerateCodeExtensions(this, resourceType); // Generate _ASP FastObjectFactory assemblyBuilder.GenerateTypeFactory(this.ResourceFullName); assemblyBuilder.AddCodeCompileUnit(this, generatedUnit); }
private void ProcessEmbeddedResource( IResourceBuildHelper helper, string source, out string preProcessed, out string compacted, List <ParseException> errors) { preProcessed = source.Replace(" ", ""); string[] parts = preProcessed.Split(TypeDelims, 2, StringSplitOptions.RemoveEmptyEntries); if (parts.Length < 2 || String.IsNullOrEmpty(parts[0]) || String.IsNullOrEmpty(parts[1])) { compacted = preProcessed = null; return; } parts[0] = MergeResourceCodeProvider.ScrubResourceName(parts[0]); // load resources from Assembly Assembly assembly = Assembly.Load(parts[1]); helper.AddAssemblyDependency(assembly); ManifestResourceInfo info = assembly.GetManifestResourceInfo(parts[0]); if (info == null) { compacted = preProcessed = null; return; } using (Stream stream = assembly.GetManifestResourceStream(parts[0])) { using (StreamReader reader = new StreamReader(stream)) { preProcessed = reader.ReadToEnd(); compacted = null; } } string ext = Path.GetExtension(parts[0]).Trim('.'); CompilerType compiler = helper.GetDefaultCompilerTypeForLanguage(ext); if (!typeof(ResourceCodeProvider).IsAssignableFrom(compiler.CodeDomProviderType)) { // don't know how to process any further compacted = preProcessed; return; } ResourceCodeProvider provider = (ResourceCodeProvider)Activator.CreateInstance(compiler.CodeDomProviderType); try { // concatenate the preprocessed source for current merge phase provider.ProcessResource( helper, parts[0], preProcessed, out preProcessed, out compacted, errors); } catch (ParseException ex) { errors.Add(ex); } catch (Exception ex) { errors.Add(new ParseError(ex.Message, parts[0], 0, 0, ex)); } if (!this.isMimeSet && !String.IsNullOrEmpty(provider.ContentType) && !String.IsNullOrEmpty(provider.FileExtension)) { this.contentType = provider.ContentType; this.fileExtension = provider.FileExtension; this.isMimeSet = true; } }