* Move extensions to resourceExporer and make non-static (#3640)

* Add fallback for stringonly reference binding "foo.xxx" => looks for "foo.xxx.dialog" and if not found attempts to bind to "foo.xxx",

The point of these changes is that it allows new extensions to be added to the resource explorer, and if there are object bindings for those extensions they will be used.

For example, this captures 2 scenarios:
1. "recognizer":"foo.lu" => will bind to lubuild output of "foo.lu.dialog"
2. "schema":"foo.schema" => will attempt to bind to foo.schema.dialog, and then fall back to foo.schema, which is a valid JSON object to bind. (Thus removing the need to have schema file be foo.schema.dialog which is kind of nonsense.

* removed some unused fields,
* cleaned up some nonsense I disovered in .csproj files
* added .qna files to pattern list
This commit is contained in:
Tom Laird-McConnell 2020-03-30 14:14:58 -07:00 коммит произвёл GitHub
Родитель fce3b0706d
Коммит f4e01bf555
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
12 изменённых файлов: 51 добавлений и 68 удалений

Просмотреть файл

@ -29,6 +29,8 @@
<Content Include="**/*.lg" />
<Content Include="**/*.lu" />
<Content Include="**/*.schema" />
<Content Include="**/*.qna"/>
<Content Include="**/*.json"/>
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -28,6 +28,8 @@
<Content Include="**/*.lg" />
<Content Include="**/*.lu" />
<Content Include="**/*.schema" />
<Content Include="**/*.qna"/>
<Content Include="**/*.json"/>
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -37,13 +37,6 @@
<NoWarn>$(NoWarn);NU1701</NoWarn>
</PropertyGroup>
<ItemGroup>
<Content Include="**/*.dialog" />
<Content Include="**/*.lg" />
<Content Include="**/*.lu" />
<Content Include="**/*.schema" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Rest.ClientRuntime" Version="2.3.21" />
<PackageReference Include="AsyncUsageAnalyzers" Version="1.0.0-alpha003" PrivateAssets="all" />

Просмотреть файл

@ -30,6 +30,8 @@
<Content Include="**/*.lg" />
<Content Include="**/*.lu" />
<Content Include="**/*.schema" />
<Content Include="**/*.qna"/>
<Content Include="**/*.json"/>
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -28,10 +28,11 @@
<ItemGroup>
<Content Include="**/*.dialog" />
<Content Include="Schemas/**/*.json" />
<Content Include="**/*.lg" />
<Content Include="**/*.lu" />
<Content Include="**/*.schema" />
<Content Include="**/*.qna"/>
<Content Include="**/*.json"/>
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -25,14 +25,6 @@
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<Content Include="**/*.dialog" />
<Content Include="schemas/**/*.json" />
<Content Include="**/*.lg" />
<Content Include="**/*.lu" />
<Content Include="**/*.schema" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Json.Pointer" Version="0.61.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />

Просмотреть файл

@ -9,7 +9,6 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
/// </summary>
public class FileResource : IResource
{
private string path;
private Task<byte[]> contentTask;
private Task<string> textTask;
@ -19,7 +18,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
/// <param name="path">path to file.</param>
public FileResource(string path)
{
this.path = path;
this.FullName = path;
this.Id = Path.GetFileName(path);
}
@ -37,10 +36,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
/// <value>
/// The full path to the resource on disk.
/// </value>
public string FullName
{
get { return this.path; }
}
public string FullName { get; }
/// <summary>
/// Open a stream to the resource.
@ -53,11 +49,11 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
this.contentTask = Task.Run(async () =>
{
Trace.TraceInformation($"Loading {this.Id}");
var fileInfo = new FileInfo(this.path);
var fileInfo = new FileInfo(this.FullName);
Stream stream = null;
try
{
stream = File.OpenRead(this.path);
stream = File.OpenRead(this.FullName);
var buffer = new byte[fileInfo.Length];
await stream.ReadAsync(buffer, 0, (int)fileInfo.Length).ConfigureAwait(false);
return buffer;

Просмотреть файл

@ -15,25 +15,26 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
/// </summary>
public class FolderResourceProvider : IResourceProvider, IDisposable
{
private CancellationTokenSource cancelReloadToken = new CancellationTokenSource();
private ConcurrentBag<string> changedPaths = new ConcurrentBag<string>();
private ResourceExplorer resourceExplorer;
private FileSystemWatcher watcher;
private Dictionary<string, FileResource> resources = new Dictionary<string, FileResource>();
/// <summary>
/// Initializes a new instance of the <see cref="FolderResourceProvider"/> class.
/// </summary>
/// <param name="resourceExplorer">resourceExplorer.</param>
/// <param name="folder">Folder.</param>
/// <param name="includeSubFolders">Should include sub folders.</param>
/// <param name="monitorChanges">Should monitor changes.</param>
public FolderResourceProvider(string folder, bool includeSubFolders = true, bool monitorChanges = true)
public FolderResourceProvider(ResourceExplorer resourceExplorer, string folder, bool includeSubFolders = true, bool monitorChanges = true)
{
this.resourceExplorer = resourceExplorer;
this.IncludeSubFolders = includeSubFolders;
folder = PathUtils.NormalizePath(folder);
this.Directory = new DirectoryInfo(folder);
SearchOption option = this.IncludeSubFolders ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
foreach (var fileInfo in this.Directory.EnumerateFiles($"*.*", option).Where(fi => Extensions.Contains(fi.Extension)))
foreach (var fileInfo in this.Directory.EnumerateFiles($"*.*", option).Where(fi => resourceExplorer.ResourceTypes.Contains(fi.Extension.TrimStart('.'))))
{
var fileResource = new FileResource(fileInfo.FullName);
this.resources[fileResource.Id] = fileResource;
@ -56,14 +57,6 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
/// </summary>
public event ResourceChangedEventHandler Changed;
/// <summary>
/// Gets the extensions that you want the FolderResourceProvider to manage.
/// </summary>
/// <value>
/// The extensions that you want the FolderResourceProvider to manage.
/// </value>
public static HashSet<string> Extensions { get; private set; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".lg", ".qna", ".lu", ".dialog", ".schema", ".md" };
/// <summary>
/// Gets or sets folder to enumerate.
/// </summary>
@ -148,7 +141,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
private void Watcher_Deleted(object sender, FileSystemEventArgs e)
{
var ext = Path.GetExtension(e.FullPath);
if (Extensions.Contains(ext))
if (this.resourceExplorer.ResourceTypes.Contains(ext.TrimStart('.')))
{
lock (this.resources)
{
@ -164,7 +157,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
private void Watcher_Renamed(object sender, RenamedEventArgs e)
{
var ext = Path.GetExtension(e.FullPath);
if (Extensions.Contains(ext))
if (this.resourceExplorer.ResourceTypes.Contains(ext.TrimStart('.')))
{
lock (this.resources)
{
@ -181,7 +174,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
private void Watcher_Changed(object sender, FileSystemEventArgs e)
{
var ext = Path.GetExtension(e.FullPath);
if (Extensions.Contains(ext))
if (this.resourceExplorer.ResourceTypes.Contains(ext.TrimStart('.')))
{
var fileResource = new FileResource(e.FullPath);

Просмотреть файл

@ -27,7 +27,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
/// <returns>The resource explorer.</returns>
public static ResourceExplorer AddFolder(this ResourceExplorer explorer, string folder, bool includeSubFolders = true, bool monitorChanges = true)
{
explorer.AddResourceProvider(new FolderResourceProvider(folder, includeSubFolders: includeSubFolders, monitorChanges: monitorChanges));
explorer.AddResourceProvider(new FolderResourceProvider(explorer, folder, includeSubFolders: includeSubFolders, monitorChanges: monitorChanges));
return explorer;
}
@ -101,7 +101,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
}
else
{
resourceExplorer.AddResourceProvider(new FolderResourceProvider(projectFolder, includeSubFolders: true, monitorChanges: monitorChanges));
resourceExplorer.AddResourceProvider(new FolderResourceProvider(resourceExplorer, projectFolder, includeSubFolders: true, monitorChanges: monitorChanges));
}
// add project references
@ -112,7 +112,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
path = Path.GetDirectoryName(path);
if (Directory.Exists(path))
{
resourceExplorer.AddResourceProvider(new FolderResourceProvider(path, includeSubFolders: true, monitorChanges: monitorChanges));
resourceExplorer.AddResourceProvider(new FolderResourceProvider(resourceExplorer, path, includeSubFolders: true, monitorChanges: monitorChanges));
}
}
@ -141,7 +141,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
var folder = Path.Combine(packages, PathUtils.NormalizePath(pathResolver.GetPackageDirectoryName(package)));
if (Directory.Exists(folder))
{
resourceExplorer.AddResourceProvider(new FolderResourceProvider(folder, includeSubFolders: true, monitorChanges: monitorChanges));
resourceExplorer.AddResourceProvider(new FolderResourceProvider(resourceExplorer, folder, includeSubFolders: true, monitorChanges: monitorChanges));
}
}
}

Просмотреть файл

@ -75,6 +75,22 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
get { return this.resourceProviders; }
}
/// <summary>
/// Gets the resource type id extensions that you want to manage.
/// </summary>
/// <value>
/// The extensions that you want the to manage.
/// </value>
public HashSet<string> ResourceTypes { get; private set; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"dialog",
"lu",
"lg",
"qna",
"schema",
"json"
};
/// <summary>
/// Add a resource provider to the resources managed by the resource explorer.
/// </summary>
@ -364,10 +380,14 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Resources
throw new InvalidOperationException("Failed to resolve reference, $copy property not present");
}
var resource = this.GetResource($"{refTarget}.dialog");
if (resource == null)
// see if there is a dialog file for this resource.id
if (!this.TryGetResource($"{refTarget}.dialog", out IResource resource))
{
throw new FileNotFoundException($"Failed to find resource named {refTarget}.dialog");
// if not, try loading the resource directly.
if (!this.TryGetResource(refTarget, out resource))
{
throw new FileNotFoundException($"Failed to find resource named {refTarget}.dialog or {refTarget}.");
}
}
string text = await resource.ReadTextAsync().ConfigureAwait(false);

Просмотреть файл

@ -27,24 +27,6 @@
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<Content Include="**/*.dialog" />
<Content Include="**/*.lg" />
<Content Include="**/*.lu" />
<Content Include="**/*.schema" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Templating\**" />
<Content Remove="Templating\**" />
<EmbeddedResource Remove="Templating\**" />
<None Remove="Templating\**" />
</ItemGroup>
<ItemGroup>
<None Remove="Schemas\Microsoft.IRecognizer.schema" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AsyncUsageAnalyzers" Version="1.0.0-alpha003" PrivateAssets="all" />
<PackageReference Include="Microsoft.Bot.Builder" Condition=" '$(IsBuildServer)' == '' " Version="4.8.0-local" />

Просмотреть файл

@ -35,7 +35,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Tests
var path = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, PathUtils.NormalizePath(@"..\..\..")));
using (var explorer = new ResourceExplorer())
{
explorer.AddResourceProvider(new FolderResourceProvider(path));
explorer.AddResourceProvider(new FolderResourceProvider(explorer, path));
await AssertResourceType(path, explorer, "dialog");
var resources = explorer.GetResources("foo").ToArray();
@ -49,7 +49,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Tests
var path = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, PathUtils.NormalizePath(@"..\..\..")));
using (var explorer = new ResourceExplorer())
{
explorer.AddResourceProvider(new FolderResourceProvider(path));
explorer.AddResourceProvider(new FolderResourceProvider(explorer, path));
try
{
explorer.GetResource("bogus.dialog");
@ -130,7 +130,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Tests
var path = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, PathUtils.NormalizePath(@"..\..\..")));
using (var explorer = new ResourceExplorer())
{
explorer.AddResourceProvider(new FolderResourceProvider(path, monitorChanges: true));
explorer.AddResourceProvider(new FolderResourceProvider(explorer, path, monitorChanges: true));
AssertResourceFound(explorer, testId);
@ -170,7 +170,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Declarative.Tests
var path = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, PathUtils.NormalizePath(@"..\..\..")));
using (var explorer = new ResourceExplorer())
{
explorer.AddResourceProvider(new FolderResourceProvider(path, monitorChanges: true));
explorer.AddResourceProvider(new FolderResourceProvider(explorer, path, monitorChanges: true));
AssertResourceFound(explorer, testId);