Add DoWhile component sample
This commit is contained in:
Родитель
27ba6ad42c
Коммит
bdcd59956f
|
@ -0,0 +1,164 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using AdaptiveExpressions.Properties;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Dialogs.Adaptive.Actions;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Components.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes a set of actions while an expression evaluates to true.
|
||||
/// </summary>
|
||||
public class DoWhile : ActionScope
|
||||
{
|
||||
/// <summary>
|
||||
/// Class identifier.
|
||||
/// </summary>
|
||||
[JsonProperty("$kind")]
|
||||
public const string Kind = "BotBuilderSamples.DoWhile";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DoWhile"/> class.
|
||||
/// </summary>
|
||||
/// <param name="sourceFilePath">Optional, full path of the source file that contains the caller.</param>
|
||||
/// <param name="sourceLineNumber">optional, line number in the source file at which the method is called.</param>
|
||||
[JsonConstructor]
|
||||
public DoWhile([CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
|
||||
: base()
|
||||
{
|
||||
RegisterSourceLocation(sourceFilePath, sourceLineNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an optional expression which if is true will disable this action.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A boolean expression.
|
||||
/// </value>
|
||||
[JsonProperty("disabled")]
|
||||
public BoolExpression Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the memory expression evaludating to a condition which determines if the DoWhile should continue.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The memory expression which determines if the DoWhile should continue.
|
||||
/// </value>
|
||||
[JsonProperty("condition")]
|
||||
public BoolExpression Condition { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an optional expression which will ensure the loop runs once, before checking the condition.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A boolean expression.
|
||||
/// </value>
|
||||
[JsonProperty("runOnce")]
|
||||
public BoolExpression RunOnce { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Called when the dialog is started and pushed onto the dialog stack.
|
||||
/// </summary>
|
||||
/// <param name="dc">The <see cref="DialogContext"/> for the current turn of conversation.</param>
|
||||
/// <param name="options">Optional, initial information to pass to the dialog.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects
|
||||
/// or threads to receive notice of cancellation.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (options is CancellationToken)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
|
||||
}
|
||||
|
||||
if (Disabled != null && Disabled.GetValue(dc.State))
|
||||
{
|
||||
return await dc.EndDialogAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if(Condition == null)
|
||||
{
|
||||
throw new InvalidOperationException("Condition is required for DoWhile.");
|
||||
}
|
||||
|
||||
// If RunOnce is false, end the dialog if Condition evaluates to true.
|
||||
if (RunOnce != null && RunOnce.GetValue(dc.State) == false)
|
||||
{
|
||||
if (Condition.GetValue(dc.State) == false)
|
||||
{
|
||||
return await dc.EndDialogAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
return await base.BeginDialogAsync(dc, options, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the dialog's action ends.
|
||||
/// </summary>
|
||||
/// <param name="dc">The <see cref="DialogContext"/> for the current turn of conversation.</param>
|
||||
/// <param name="result">Optional, value returned from the dialog that was called. The type
|
||||
/// of the value returned is dependent on the child dialog.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects
|
||||
/// or threads to receive notice of cancellation.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
protected override async Task<DialogTurnResult> OnEndOfActionsAsync(DialogContext dc, object result = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (Condition.GetValue(dc.State))
|
||||
{
|
||||
return await BeginActionAsync(dc, 0, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return await base.OnEndOfActionsAsync(dc, result, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Called when a returning control to this dialog with an <see cref="ActionScopeResult"/>
|
||||
/// with the property ActionCommand set to <c>BreakLoop</c>.
|
||||
/// </summary>
|
||||
/// <param name="dc">The dialog context for the current turn of the conversation.</param>
|
||||
/// <param name="actionScopeResult">Contains the actions scope result.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects
|
||||
/// or threads to receive notice of cancellation.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
protected override async Task<DialogTurnResult> OnBreakLoopAsync(DialogContext dc, ActionScopeResult actionScopeResult, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await dc.EndDialogAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a returning control to this dialog with an <see cref="ActionScopeResult"/>
|
||||
/// with the property ActionCommand set to <c>ContinueLoop</c>.
|
||||
/// </summary>
|
||||
/// <param name="dc">The dialog context for the current turn of the conversation.</param>
|
||||
/// <param name="actionScopeResult">Contains the actions scope result.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects
|
||||
/// or threads to receive notice of cancellation.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
protected override async Task<DialogTurnResult> OnContinueLoopAsync(DialogContext dc, ActionScopeResult actionScopeResult, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (Condition.GetValue(dc.State))
|
||||
{
|
||||
return await BeginActionAsync(dc, 0, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return await base.OnEndOfActionsAsync(dc, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds the compute Id for the dialog.
|
||||
/// </summary>
|
||||
/// <returns>A string representing the compute Id.</returns>
|
||||
protected override string OnComputeId()
|
||||
{
|
||||
return $"{GetType().Name}({Condition?.ToString()})";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using AdaptiveExpressions.Converters;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs.Debugging;
|
||||
using Microsoft.Bot.Builder.Dialogs.Declarative;
|
||||
using Microsoft.Bot.Builder.Dialogs.Declarative.Resources;
|
||||
using Microsoft.BotBuilderSamples.Components.Actions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="ComponentRegistration"/> for DoWhile enabling discovering assets.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// To make your components available to the system you derive from ComponentRegistration
|
||||
/// and implement appropriate interfaces which register functionality. These components
|
||||
/// then are consumed in appropriate places by the systems that need them.
|
||||
/// </remarks>
|
||||
public class DoWhileComponentRegistration : ComponentRegistration, IComponentDeclarativeTypes
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DoWhileComponentRegistration"/> class.
|
||||
/// </summary>
|
||||
public DoWhileComponentRegistration()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets adaptive <see cref="DeclarativeType"/> resources.
|
||||
/// </summary>
|
||||
/// <param name="resourceExplorer"><see cref="ResourceExplorer"/> with expected path to get all schema resources.</param>
|
||||
/// <returns>Adaptive <see cref="DeclarativeType"/> resources.</returns>
|
||||
public virtual IEnumerable<DeclarativeType> GetDeclarativeTypes(ResourceExplorer resourceExplorer)
|
||||
{
|
||||
yield return new DeclarativeType<DoWhile>(DoWhile.Kind);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets adaptive <see cref="JsonConverter"/> resources.
|
||||
/// </summary>
|
||||
/// <param name="resourceExplorer">ResourceExplorer to use to resolve references.</param>
|
||||
/// <param name="sourceContext">SourceContext to build debugger source map.</param>
|
||||
/// <returns>Adaptive <see cref="JsonConverter"/> resources.</returns>
|
||||
public virtual IEnumerable<JsonConverter> GetConverters(ResourceExplorer resourceExplorer, SourceContext sourceContext)
|
||||
{
|
||||
yield return new ObjectExpressionConverter<object>();
|
||||
}
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 37 KiB |
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Runtime.Plugins;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Components
|
||||
{
|
||||
/// <summary>
|
||||
// Represents a plugin to be utilized within the bot runtime that can provide access
|
||||
// to additional components that implement well-defined interfaces in the Bot Framework
|
||||
// SDK.
|
||||
/// </summary>
|
||||
public class DoWhilePlugin : IBotPlugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Load the contents of the plugin into the bot runtime.
|
||||
/// </summary>
|
||||
/// <param name="context">Load context that provides access to application configuration and service collection.</param>
|
||||
public void Load(IBotPluginLoadContext context)
|
||||
{
|
||||
ComponentRegistration.Add(new DoWhileComponentRegistration());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2020 - present Microsoft Corporation
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,47 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<RepositoryUrl>https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/csharp_dotnetcore/101.components-dowhile</RepositoryUrl>
|
||||
<PackageIcon>package-icon.png</PackageIcon>
|
||||
<PackageLicenseUrl />
|
||||
<PackageLicenseExpression></PackageLicenseExpression>
|
||||
<Description>Sample composer action to execute a loop while a condition is true.</Description>
|
||||
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
|
||||
<PackageProjectUrl>https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/csharp_dotnetcore/101.components-dowhile</PackageProjectUrl>
|
||||
<Version>1.0.1-preview</Version>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageTags>bf-component</PackageTags>
|
||||
<ContentTargetFolders>content</ContentTargetFolders>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Runtime.Plugins" Version="4.12.0-preview" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Dialogs.Adaptive" Version="4.12.0" />
|
||||
<PackageReference Include="ParallelExtensionsExtras.CrossPlatform" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="**/*.dialog" />
|
||||
<Content Include="**/*.lg" />
|
||||
<Content Include="**/*.lu" />
|
||||
<Content Include="**/*.schema" />
|
||||
<Content Include="**/*.uischema" />
|
||||
<Content Include="**/*.qna" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Schemas\BotBuilderSamples.DoWhile.schema" />
|
||||
<None Remove="Schemas\BotBuilderSamples.DoWhile.uischema" />
|
||||
<None Include="LICENSE.md">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath></PackagePath>
|
||||
</None>
|
||||
<None Include="package-icon.png">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath></PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"$schema": "https://schemas.botframework.com/schemas/component/v1.0/component.schema",
|
||||
"$role": "implements(Microsoft.IDialog)",
|
||||
"title": "DoWhile",
|
||||
"description": "Performs a set of actions while a condition is true.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"title": "Id",
|
||||
"description": "Optional id for the dialog"
|
||||
},
|
||||
"disabled": {
|
||||
"$ref": "schema:#/definitions/booleanExpression",
|
||||
"title": "Disabled",
|
||||
"description": "Optional condition which if true will disable this action.",
|
||||
"examples": [
|
||||
"user.age > 3"
|
||||
]
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "schema:#/definitions/booleanExpression",
|
||||
"title": "Condition",
|
||||
"description": "Name of the property with the array of dialogs to call.",
|
||||
"examples": [
|
||||
"dialog.dialogList"
|
||||
]
|
||||
},
|
||||
"runOnce": {
|
||||
"$ref": "schema:#/definitions/booleanExpression",
|
||||
"title": "Run once",
|
||||
"description": "Execute the actions once, before checking the condition.",
|
||||
"default": true
|
||||
},
|
||||
"actions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$kind": "Microsoft.IDialog"
|
||||
},
|
||||
"title": "Actions",
|
||||
"description": "Actions to execute while the condition is true."
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"$schema": "https://schemas.botframework.com/schemas/ui/v1.0/ui.schema",
|
||||
"form": {
|
||||
"label": "Do actions while condition is true",
|
||||
"subtitle": "DoWhile",
|
||||
"helpLink": "https://aka.ms/bfc-understanding-dialogs",
|
||||
"order": [
|
||||
"condition",
|
||||
"runOnce",
|
||||
"*"
|
||||
],
|
||||
"hidden": [
|
||||
"actions"
|
||||
],
|
||||
"properties": {
|
||||
"condition": {
|
||||
"intellisenseScopes": [
|
||||
"variable-scopes"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"menu": {
|
||||
"label": "DoWhile loop",
|
||||
"submenu": [ "Looping" ]
|
||||
},
|
||||
"flow": {
|
||||
"widget": "ForeachWidget",
|
||||
"nowrap": true,
|
||||
"loop": {
|
||||
"widget": "ActionCard",
|
||||
"body": "=action.condition"
|
||||
}
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 19 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 15 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 7.7 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 96 KiB |
|
@ -0,0 +1,74 @@
|
|||
# DoWhile Component
|
||||
|
||||
This sample demonstrates how to extend [Bot Framework Composer](https://docs.microsoft.com/en-us/composer/introduction) with a new DoWhile custom action component.
|
||||
|
||||
The following classes and schema files are included in the project:
|
||||
|
||||
| File | Description |
|
||||
| ------ | ------ |
|
||||
| [DoWhile.cs](#DoWhile) | Inherits from ActionScope and manages execution of a block of actions supporting Break and Continue semantics.. |
|
||||
| [DoWhilePlugin.cs](#Plugin) | Loaded by the adaptive runtime DependencyInjection Abstractions and calls ComponentRegistration, adding DoWhileComponentRegistration. |
|
||||
| [DoWhileComponentRegistration.cs](#ComponentRegistration) | Registers the DoWhile component with the adaptive dialog system. |
|
||||
| [.schema](#schema) | Declarative definition of the DoWhile component. |
|
||||
| [.uischema](#uischema) | DoWhile component visual interface declarative definition. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Bot Framework Composer](https://docs.microsoft.com/en-us/composer/install-composer) version 1.3.1
|
||||
- [.NET Core SDK](https://dotnet.microsoft.com/download) version 3.1
|
||||
- [nuget.exe](https://www.nuget.org/downloads) recommended latest
|
||||
- A local package feed is required. See ([nuget local feed](https://docs.microsoft.com/en-us/nuget/hosting-packages/local-feeds)) for details.
|
||||
|
||||
## To try this sample
|
||||
|
||||
1) Clone the repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Microsoft/botbuilder-samples.git
|
||||
```
|
||||
|
||||
2) If you are using Visual Studio
|
||||
- Launch Visual Studio
|
||||
- File -> Open -> Project/Solution
|
||||
- Navigate to `samples/csharp_dotnetcore/101.components-dowhile` folder
|
||||
- Select `Microsoft.BotBuilderSamples.Components.DoWhile.csproj` file
|
||||
- Building the project
|
||||
|
||||
3) The .nupkg should now be in the bin folder. Next, run `nuget add`
|
||||
|
||||
```bash
|
||||
nuget add Microsoft.BotBuilderSamples.Components.DoWhile.1.0.0-preview.nupkg -source c:\nuget
|
||||
```
|
||||
|
||||
## Composer
|
||||
|
||||
### Package Installation
|
||||
|
||||
Add the local package feed to Composer
|
||||
![Local Package Feed](package-feed.png)
|
||||
|
||||
The local package can now be installed from composers Package Manager screen. Just select the package from the list and click install.
|
||||
|
||||
![Package Manager](package-manager.png)
|
||||
|
||||
### Usage
|
||||
|
||||
Once installed you should find the DoWhile action under the "Looping" menu.
|
||||
|
||||
![Action Menu](new-menu.png)
|
||||
|
||||
|
||||
#### Do While
|
||||
|
||||
Add the DoWhile action to a dialog, and add some child actions. Ensure the condition will eventually resolve to `true`.
|
||||
|
||||
![DoWhile Dialog](DoWhileDialog.png)
|
||||
|
||||
|
||||
## Deploy the bot to Azure
|
||||
|
||||
To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](https://aka.ms/azuredeployment) for a complete list of deployment instructions.
|
||||
|
||||
## Further reading
|
||||
|
||||
- [Add custom actions](https://docs.microsoft.com/en-us/composer/how-to-add-custom-action)
|
Загрузка…
Ссылка в новой задаче