#4528 Support embedded files with manifest created by Microsoft.Extensions.FileProviders.Embedded

pull/4540/head
Halil İbrahim Kalkan 5 years ago
parent bc9bed8b61
commit 1154962d4d

@ -17,6 +17,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Composite" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.1.5" />
</ItemGroup>
<ItemGroup>

@ -3,7 +3,7 @@
public class AbpVirtualFileSystemOptions
{
public VirtualFileSetList FileSets { get; }
public AbpVirtualFileSystemOptions()
{
FileSets = new VirtualFileSetList();

@ -8,7 +8,7 @@ using Microsoft.Extensions.FileProviders;
namespace Volo.Abp.VirtualFileSystem.Embedded
{
public class EmbeddedFileSet : IVirtualFileSet
public class EmbeddedFileSet : DictionaryBasedFileProvider
{
[NotNull]
public Assembly Assembly { get; }
@ -16,19 +16,22 @@ namespace Volo.Abp.VirtualFileSystem.Embedded
[CanBeNull]
public string BaseNamespace { get; }
[CanBeNull]
public string BaseFolderInProject { get; }
protected override IDictionary<string, IFileInfo> Files => _files.Value;
private readonly Lazy<Dictionary<string, IFileInfo>> _files;
public EmbeddedFileSet(
[NotNull] Assembly assembly,
[CanBeNull] string baseNamespace = null,
[CanBeNull] string baseFolderInProject = null)
[CanBeNull] string baseNamespace = null)
{
Check.NotNull(assembly, nameof(assembly));
Assembly = assembly;
BaseNamespace = baseNamespace;
BaseFolderInProject = baseFolderInProject;
_files = new Lazy<Dictionary<string, IFileInfo>>(
CreateFiles,
true
);
}
public void AddFiles(Dictionary<string, IFileInfo> files)
@ -127,5 +130,17 @@ namespace Volo.Abp.VirtualFileSystem.Embedded
return filePath.Substring(filePath.LastIndexOf("/", StringComparison.Ordinal) + 1);
}
protected override string NormalizePath(string subpath)
{
return VirtualFilePathHelper.NormalizePath(subpath);
}
private Dictionary<string, IFileInfo> CreateFiles()
{
var files = new Dictionary<string, IFileInfo>(StringComparer.OrdinalIgnoreCase);
AddFiles(files);
return files;
}
}
}

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Options;
@ -28,6 +27,11 @@ namespace Volo.Abp.VirtualFileSystem
public virtual IDirectoryContents GetDirectoryContents(string subpath)
{
if (subpath == "")
{
subpath = "/";
}
return _hybridFileProvider.GetDirectoryContents(subpath);
}
@ -42,52 +46,12 @@ namespace Volo.Abp.VirtualFileSystem
fileProviders.Add(dynamicFileProvider);
if (_options.FileSets.PhysicalPaths.Any())
foreach (var fileSet in _options.FileSets.AsEnumerable().Reverse())
{
fileProviders.AddRange(
_options.FileSets.PhysicalPaths
.Select(rootPath => new PhysicalFileProvider(rootPath))
.Reverse()
);
fileProviders.Add(fileSet.FileProvider);
}
fileProviders.Add(new InternalVirtualFileProvider(_options));
return new CompositeFileProvider(fileProviders);
}
protected class InternalVirtualFileProvider : DictionaryBasedFileProvider
{
protected override IDictionary<string, IFileInfo> Files => _files.Value;
private readonly AbpVirtualFileSystemOptions _options;
private readonly Lazy<Dictionary<string, IFileInfo>> _files;
public InternalVirtualFileProvider(AbpVirtualFileSystemOptions options)
{
_options = options;
_files = new Lazy<Dictionary<string, IFileInfo>>(
CreateFiles,
true
);
}
private Dictionary<string, IFileInfo> CreateFiles()
{
var files = new Dictionary<string, IFileInfo>(StringComparer.OrdinalIgnoreCase);
foreach (var set in _options.FileSets)
{
set.AddFiles(files);
}
return files;
}
protected override string NormalizePath(string subpath)
{
return VirtualFilePathHelper.NormalizePath(subpath);
}
}
}
}

@ -0,0 +1,35 @@
using System.IO;
using System.Reflection;
using Microsoft.Extensions.FileProviders;
namespace Volo.Abp.VirtualFileSystem
{
public class VirtualFileSetInfo
{
public IFileProvider FileProvider
{
get => _fileProvider;
set => _fileProvider = Check.NotNull(value, nameof(value));
}
private IFileProvider _fileProvider;
public VirtualFileSetInfo(IFileProvider fileProvider)
{
FileProvider = fileProvider;
}
}
public class EmbeddedVirtualFileSetInfo : VirtualFileSetInfo
{
public Assembly Assembly { get; }
public string BaseFolder { get; }
public EmbeddedVirtualFileSetInfo(IFileProvider fileProvider, Assembly assembly, string baseFolder = null)
: base(fileProvider)
{
Assembly = assembly;
BaseFolder = baseFolder;
}
}
}

@ -2,13 +2,8 @@
namespace Volo.Abp.VirtualFileSystem
{
public class VirtualFileSetList : List<IVirtualFileSet>
public class VirtualFileSetList : List<VirtualFileSetInfo>
{
public List<string> PhysicalPaths { get; }
public VirtualFileSetList()
{
PhysicalPaths = new List<string>();
}
}
}

@ -1,44 +1,76 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Extensions.FileProviders;
using Volo.Abp.VirtualFileSystem.Embedded;
namespace Volo.Abp.VirtualFileSystem
{
public static class VirtualFileSetListExtensions
{
public static void AddEmbedded<T>([NotNull] this VirtualFileSetList list, [CanBeNull] string baseNamespace = null, string baseFolderInProject = null)
public static void AddEmbedded<T>(
[NotNull] this VirtualFileSetList list,
[CanBeNull] string baseNamespace = null,
[CanBeNull] string baseFolder = null)
{
Check.NotNull(list, nameof(list));
list.Add(
new EmbeddedFileSet(
typeof(T).Assembly,
baseNamespace,
baseFolderInProject
)
var assembly = typeof(T).Assembly;
var fileProvider = CreateFileProvider(
assembly,
baseNamespace,
baseFolder
);
list.Add(new EmbeddedVirtualFileSetInfo(fileProvider, assembly, baseFolder));
}
public static void ReplaceEmbeddedByPhysical<T>([NotNull] this VirtualFileSetList list, [NotNull] string pyhsicalPath)
private static IFileProvider CreateFileProvider(
[NotNull] Assembly assembly,
[CanBeNull] string baseNamespace = null,
[CanBeNull] string baseFolder = null)
{
Check.NotNull(list, nameof(list));
Check.NotNull(pyhsicalPath, nameof(pyhsicalPath));
Check.NotNull(assembly, nameof(assembly));
var assembly = typeof(T).Assembly;
var embeddedFileSets = list.OfType<EmbeddedFileSet>().Where(fs => fs.Assembly == assembly).ToList();
var info = assembly.GetManifestResourceInfo("Microsoft.Extensions.FileProviders.Embedded.Manifest.xml");
foreach (var embeddedFileSet in embeddedFileSets)
if (info == null)
{
list.Remove(embeddedFileSet);
return new EmbeddedFileSet(assembly, baseNamespace);
}
if (baseFolder == null)
{
return new ManifestEmbeddedFileProvider(assembly);
}
return new ManifestEmbeddedFileProvider(assembly, baseFolder);
}
public static void ReplaceEmbeddedByPhysical<T>(
[NotNull] this VirtualFileSetList fileSets,
[NotNull] string pyhsicalPath)
{
Check.NotNull(fileSets, nameof(fileSets));
Check.NotNullOrWhiteSpace(pyhsicalPath, nameof(pyhsicalPath));
var assembly = typeof(T).Assembly;
if (!embeddedFileSet.BaseFolderInProject.IsNullOrEmpty())
for (var i = 0; i < fileSets.Count; i++)
{
if (fileSets[i] is EmbeddedVirtualFileSetInfo embeddedVirtualFileSet &&
embeddedVirtualFileSet.Assembly == assembly)
{
pyhsicalPath = Path.Combine(pyhsicalPath, embeddedFileSet.BaseFolderInProject);
}
var thisPath = pyhsicalPath;
list.PhysicalPaths.Add(pyhsicalPath);
if (!embeddedVirtualFileSet.BaseFolder.IsNullOrEmpty())
{
thisPath = Path.Combine(thisPath, embeddedVirtualFileSet.BaseFolder);
}
fileSets[i] = new VirtualFileSetInfo(new PhysicalFileProvider(thisPath));
}
}
}
}

@ -4,6 +4,7 @@
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
<RootNamespace />
</PropertyGroup>
@ -15,6 +16,7 @@
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.VirtualFileSystem\Volo.Abp.VirtualFileSystem.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.1.5" />
</ItemGroup>
</Project>

@ -1,5 +1,4 @@
using System;
using System.IO;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
@ -34,6 +33,22 @@ namespace Volo.Abp.VirtualFileSystem
Encoding.UTF8.GetString(stream.GetAllBytes()).ShouldBe("//jquery-3-1-1-min.js-contents");
}
}
[Fact]
public void Should_Define_And_Get_Embedded_Resources_With_Special_Chars()
{
//Act
var resource = _virtualFileProvider.GetFileInfo("/js/my{test}.2.9.min.js");
//Assert
resource.ShouldNotBeNull();
resource.Exists.ShouldBeTrue();
using (var stream = resource.CreateReadStream())
{
Encoding.UTF8.GetString(stream.GetAllBytes()).ShouldBe("//my{test}.2.9.min.js-content");
}
}
[Fact]
public void Should_Define_And_Get_Embedded_Directory_Contents()
@ -45,7 +60,9 @@ namespace Volo.Abp.VirtualFileSystem
contents.Exists.ShouldNotBeNull();
var contentList = contents.ToList();
contentList.ShouldContain(x => x.Name == "jquery-3-1-1-min.js");
contentList.ShouldContain(x => x.Name == "my{test}.2.9.min.js");
}
[Theory]
@ -70,7 +87,9 @@ namespace Volo.Abp.VirtualFileSystem
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<TestModule>("Volo.Abp.VirtualFileSystem.MyResources");
options.FileSets.AddEmbedded<TestModule>(
baseFolder: "/Volo/Abp/VirtualFileSystem/MyResources"
);
});
}
}

@ -5,8 +5,9 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>MyCompanyName.MyProjectName</RootNamespace>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\modules\identity\src\Volo.Abp.Identity.Domain.Shared\Volo.Abp.Identity.Domain.Shared.csproj" />
<ProjectReference Include="..\..\..\..\..\modules\identityserver\src\Volo.Abp.IdentityServer.Domain.Shared\Volo.Abp.IdentityServer.Domain.Shared.csproj" />
@ -23,4 +24,9 @@
<Content Remove="Localization\MyProjectName\*.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="MyFolder\*.*" />
<Content Remove="MyFolder\*.*" />
</ItemGroup>
</Project>

Loading…
Cancel
Save