Composable type loader first iteration. Still pending:
+Activities from text +Lots of negative tests (and their error messages) + Dispatch dialog fix (doesn't work as-is) +FormFlow test +Change $type to @type +Plugin model +Recognizers converter +further schema validation
This commit is contained in:
Родитель
4d0c58fd9e
Коммит
7353c5642d
|
@ -82,9 +82,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Dialo
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Dialogs.Flows.Tests", "tests\Microsoft.Bot.Builder.Dialogs.Flow.Tests\Microsoft.Bot.Builder.Dialogs.Flows.Tests.csproj", "{0027D023-2E4C-4298-81A0-DC8BA8577116}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Expressions", "libraries\Microsoft.CommonExpressions\Microsoft.Expressions.csproj", "{68899A42-6375-43BC-95BB-2E4798D2C0EB}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Expressions", "libraries\Microsoft.CommonExpressions\Microsoft.Expressions.csproj", "{68899A42-6375-43BC-95BB-2E4798D2C0EB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Expressions.Tests", "tests\Microsoft.Expressions.Tests\Microsoft.Expressions.Tests.csproj", "{A7637631-40EF-4E8D-A90A-422A5FD593D1}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Expressions.Tests", "tests\Microsoft.Expressions.Tests\Microsoft.Expressions.Tests.csproj", "{A7637631-40EF-4E8D-A90A-422A5FD593D1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Dialogs.Flow.Loader", "libraries\Microsoft.Bot.Builder.Dialogs.Flow.Loader\Microsoft.Bot.Builder.Dialogs.Flow.Loader.csproj", "{1BC05915-044E-4776-8956-B44BBEFF2F84}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Dialogs.Flow.Loader.Tests", "tests\Microsoft.Bot.Builder.Dialogs.Flow.Loader.Tests\Microsoft.Bot.Builder.Dialogs.Flow.Loader.Tests.csproj", "{CD473E17-DA3C-4E64-9AC6-31B4FB6D69E7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -391,6 +395,22 @@ Global
|
|||
{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031}.Documentation|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D790A4BB-D8AC-4AAE-B3FE-0CF432CA8031}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Documentation|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Documentation|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CD473E17-DA3C-4E64-9AC6-31B4FB6D69E7}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CD473E17-DA3C-4E64-9AC6-31B4FB6D69E7}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CD473E17-DA3C-4E64-9AC6-31B4FB6D69E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CD473E17-DA3C-4E64-9AC6-31B4FB6D69E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CD473E17-DA3C-4E64-9AC6-31B4FB6D69E7}.Documentation|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CD473E17-DA3C-4E64-9AC6-31B4FB6D69E7}.Documentation|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CD473E17-DA3C-4E64-9AC6-31B4FB6D69E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CD473E17-DA3C-4E64-9AC6-31B4FB6D69E7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -437,6 +457,8 @@ Global
|
|||
{0027D023-2E4C-4298-81A0-DC8BA8577116} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{68899A42-6375-43BC-95BB-2E4798D2C0EB} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{A7637631-40EF-4E8D-A90A-422A5FD593D1} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{1BC05915-044E-4776-8956-B44BBEFF2F84} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{CD473E17-DA3C-4E64-9AC6-31B4FB6D69E7} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {7173C9F3-A7F9-496E-9078-9156E35D6E16}
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
<PackageReference Include="Microsoft.Recognizers.Text.DateTime" Version="1.1.3" />
|
||||
<PackageReference Include="Microsoft.Recognizers.Text.Number" Version="1.1.3" />
|
||||
<PackageReference Include="Microsoft.Recognizers.Text.Sequence" Version="1.1.3" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="Schema.NET" Version="3.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Dialogs.Flow;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Flow.Loader.Contract
|
||||
{
|
||||
public class DialogInfo
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public IDialog Dialog { get; set; }
|
||||
public List<IDialogCommand> Commands { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Flow.Loader.Contract
|
||||
{
|
||||
public class DialogsInfo
|
||||
{
|
||||
[JsonProperty(PropertyName = "initialNodeId")]
|
||||
public string InitialNodeId { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "Dialogs")]
|
||||
public List<DialogInfo> Dialogs { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Dialogs.Composition;
|
||||
using Microsoft.Bot.Builder.Dialogs.Composition.Expressions;
|
||||
using Microsoft.Bot.Builder.Dialogs.Flow.Loader.Types;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Flow.Loader.Converters
|
||||
{
|
||||
public class ActivityConverter : JsonConverter
|
||||
{
|
||||
public override bool CanRead => true;
|
||||
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(IActivity);
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.ValueType == typeof(string))
|
||||
{
|
||||
// If we expect an activity but find text, it is a short expression for a message activity
|
||||
return new Activity()
|
||||
{
|
||||
Type = ActivityTypes.Message,
|
||||
Text = (string)reader.Value
|
||||
};
|
||||
}
|
||||
return serializer.Deserialize<Activity>(reader);
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
serializer.Serialize(writer, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Bot.Builder.Dialogs.Flow;
|
||||
using Microsoft.Bot.Builder.Dialogs.Flow.Loader.Types;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Flow.Loader.Converters
|
||||
{
|
||||
public class DialogCommandConverter : JsonConverter
|
||||
{
|
||||
public override bool CanRead => true;
|
||||
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(IDialogCommand);
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
var jsonObject = JObject.Load(reader);
|
||||
|
||||
var typeName = jsonObject["$type"].ToString();
|
||||
var dialogCommand = Factory.Build<IDialogCommand>(typeName, jsonObject, serializer);
|
||||
|
||||
return dialogCommand;
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
serializer.Serialize(writer, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Dialogs.Composition;
|
||||
using Microsoft.Bot.Builder.Dialogs.Flow.Loader.Types;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Flow.Loader.Converters
|
||||
{
|
||||
public class DialogConverter : JsonConverter
|
||||
{
|
||||
public override bool CanRead => true;
|
||||
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(IDialog);
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
var jsonObject = JObject.Load(reader);
|
||||
var dialog = default(IDialog);
|
||||
|
||||
var typeName = jsonObject["$type"].ToString();
|
||||
IDialog dialogCommand = Factory.Build<IDialog>(typeName, jsonObject, serializer);
|
||||
|
||||
return dialogCommand;
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
serializer.Serialize(writer, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Dialogs.Composition;
|
||||
using Microsoft.Bot.Builder.Dialogs.Composition.Expressions;
|
||||
using Microsoft.Bot.Builder.Dialogs.Flow.Loader.Types;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Flow.Loader.Converters
|
||||
{
|
||||
public class ExpressionConverter : JsonConverter
|
||||
{
|
||||
public override bool CanRead => true;
|
||||
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(IExpressionEval);
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.ValueType == typeof(string))
|
||||
{
|
||||
return new CommonExpression((string)reader.Value);
|
||||
}
|
||||
throw new JsonSerializationException("Expected string expression.");
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
serializer.Serialize(writer, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Bot.Builder.Dialogs.Flow.Loader.Contract;
|
||||
using Microsoft.Bot.Builder.Dialogs.Flow.Loader.Converters;
|
||||
using Microsoft.Bot.Builder.Dialogs.Flow.Loader.Types;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Flow.Loader
|
||||
{
|
||||
public static class DialogLoader
|
||||
{
|
||||
public static IDialog Load(string json)
|
||||
{
|
||||
var flowInfo = JsonConvert.DeserializeObject<DialogsInfo>(
|
||||
json, new JsonSerializerSettings()
|
||||
{
|
||||
Binder = new Binder(),
|
||||
TypeNameHandling = TypeNameHandling.Auto,
|
||||
Converters = new List<JsonConverter>()
|
||||
{
|
||||
new DialogCommandConverter(),
|
||||
new DialogConverter(),
|
||||
new ExpressionConverter(),
|
||||
new ActivityConverter()
|
||||
}
|
||||
});
|
||||
|
||||
var rootDialog = new ComponentDialog()
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
InitialDialogId = flowInfo.InitialNodeId
|
||||
};
|
||||
|
||||
foreach (var flowNodeInfo in flowInfo.Dialogs)
|
||||
{
|
||||
rootDialog.AddDialog(flowNodeInfo.Dialog);
|
||||
|
||||
var flowDialog = new FlowDialog()
|
||||
{
|
||||
Id = flowNodeInfo.Id,
|
||||
DialogId = flowNodeInfo.Dialog.Id,
|
||||
OnCompleted = new CommandSet()
|
||||
{
|
||||
Commands = flowNodeInfo.Commands
|
||||
}
|
||||
};
|
||||
|
||||
rootDialog.AddDialog(flowDialog);
|
||||
}
|
||||
|
||||
return rootDialog;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Flow.Loader.Loaders
|
||||
{
|
||||
public class DefaultLoader : ILoader
|
||||
{
|
||||
public object Load(JObject obj, JsonSerializer serializer, Type type)
|
||||
{
|
||||
return obj.ToObject(type, serializer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Flow.Loader.Loaders
|
||||
{
|
||||
public interface ILoader
|
||||
{
|
||||
object Load(JObject obj, JsonSerializer serializer, Type type);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Bot.Builder.Dialogs.Composition.Expressions;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Flow.Loader.Loaders
|
||||
{
|
||||
public class SetVariableCommandLoader : ILoader
|
||||
{
|
||||
public object Load(JObject obj, JsonSerializer serializer, Type type)
|
||||
{
|
||||
// Allow expressions for the Value property in string format directly
|
||||
// Example:
|
||||
// "Name": "Age",
|
||||
// "Value": "DialogTurnResult.Result"
|
||||
if (obj["Value"].Type == JTokenType.String)
|
||||
{
|
||||
return new SetVariable()
|
||||
{
|
||||
Name = obj.Value<string>("Name"),
|
||||
Value = new CommonExpression(obj.Value<string>("Value"))
|
||||
};
|
||||
}
|
||||
return obj.ToObject(type, serializer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\libraries\Microsoft.Bot.Builder.Dialogs.Composition\Microsoft.Bot.Builder.Dialogs.Composition.csproj" />
|
||||
<ProjectReference Include="..\libraries\Microsoft.Bot.Builder.Dialogs.Flow\Microsoft.Bot.Builder.Dialogs.Flow.csproj" />
|
||||
<ProjectReference Include="..\libraries\Microsoft.Bot.Builder.Dialogs\Microsoft.Bot.Builder.Dialogs.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System">
|
||||
<HintPath>System</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Flow.Loader.Types
|
||||
{
|
||||
public class Binder : DefaultSerializationBinder
|
||||
{
|
||||
public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
|
||||
{
|
||||
assemblyName = null;
|
||||
typeName = Factory.NameFromType(serializedType).ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(typeName))
|
||||
{
|
||||
base.BindToName(serializedType, out assemblyName, out typeName);
|
||||
}
|
||||
}
|
||||
|
||||
public override Type BindToType(string assemblyName, string typeName)
|
||||
{
|
||||
var type = Factory.TypeFromName(typeName);
|
||||
|
||||
if (type != default(Type))
|
||||
{
|
||||
return type;
|
||||
}
|
||||
return base.BindToType(assemblyName, typeName);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Bot.Builder.Dialogs.Flow.Loader.Loaders;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Flow.Loader.Types
|
||||
{
|
||||
public static class Factory
|
||||
{
|
||||
private static Dictionary<Type, ILoader> builders = new Dictionary<Type, ILoader>();
|
||||
private static Dictionary<string, Type> types = new Dictionary<string, Type>();
|
||||
private static Dictionary<Type, string> names = new Dictionary<Type, string>();
|
||||
|
||||
static Factory()
|
||||
{
|
||||
//TODO: we don't want this static initialization, leaving it here for convenience now
|
||||
// while things are changing rapidly still
|
||||
|
||||
// Commands
|
||||
Register("http://schemas.botframework.com/SetVariable", typeof(SetVariable), new SetVariableCommandLoader());
|
||||
Register("http://schemas.botframework.com/Switch", typeof(Switch));
|
||||
Register("http://schemas.botframework.com/CallDialog", typeof(CallDialog));
|
||||
Register("http://schemas.botframework.com/SendActivity", typeof(SendActivity));
|
||||
|
||||
// Dialogs
|
||||
Register("http://schemas.botframework.com/TextPrompt", typeof(TextPrompt));
|
||||
Register("http://schemas.botframework.com/IntNumberPrompt", typeof(NumberPrompt<Int32>));
|
||||
|
||||
// Recognizers
|
||||
}
|
||||
|
||||
public static void Register(string name, Type type, ILoader loader = null)
|
||||
{
|
||||
// Default loader if none specified
|
||||
if (loader == null)
|
||||
{
|
||||
loader = new DefaultLoader();
|
||||
}
|
||||
|
||||
types.Add(name, type);
|
||||
names.Add(type, name);
|
||||
builders.Add(type, loader);
|
||||
}
|
||||
|
||||
public static T Build<T>(string name, JObject obj, JsonSerializer serializer) where T : class
|
||||
{
|
||||
ILoader builder;
|
||||
var type = TypeFromName(name);
|
||||
var found = builders.TryGetValue(type, out builder);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
// TODO: This is probably too rigid. If there is a type we don't know, consider just ignoring
|
||||
// or a smarter strategy. Write a test for this scenario and revisit this code.
|
||||
throw new ArgumentException($"Type {name} not registered in factory.");
|
||||
}
|
||||
|
||||
var built = builder.Load(obj, serializer, type);
|
||||
|
||||
var result = built as T;
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
throw new Exception($"Factory registration for name {name} resulted in type {built.GetType()}, but expected assignable to {typeof(T)}");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Type TypeFromName(string name)
|
||||
{
|
||||
Type type;
|
||||
return types.TryGetValue(name, out type) ? type : default(Type);
|
||||
}
|
||||
|
||||
public static string NameFromType(Type type)
|
||||
{
|
||||
string name;
|
||||
return names.TryGetValue(type, out name) ? name: default(string);
|
||||
}
|
||||
|
||||
// Plugins
|
||||
//public static void Register<T>(string friendlyName, Type dotnetType, Assembly assembly, Func<JsonReader, JsonSerializer, T> builder)
|
||||
//{
|
||||
|
||||
//}
|
||||
}
|
||||
}
|
|
@ -123,13 +123,18 @@ namespace Microsoft.Bot.Builder.Dialogs
|
|||
await OnEndDialogAsync(turnContext, instance, reason, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public ComponentDialog AddDialog(Dialog dialog)
|
||||
{
|
||||
return AddDialog(dialog as IDialog);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a dialog to the component dialog.
|
||||
/// </summary>
|
||||
/// <param name="dialog">The dialog to add.</param>
|
||||
/// <returns>The updated <see cref="ComponentDialog"/>.</returns>
|
||||
/// <remarks>Adding a new dialog will inherit the <see cref="IBotTelemetryClient"/> of the ComponentDialog.</remarks>
|
||||
public ComponentDialog AddDialog(Dialog dialog)
|
||||
public ComponentDialog AddDialog(IDialog dialog)
|
||||
{
|
||||
if (string.IsNullOrEmpty(dialog.Id))
|
||||
{
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Microsoft.Bot.Builder.Dialogs
|
|||
where T : struct
|
||||
{
|
||||
public NumberPrompt(string dialogId = nameof(NumberPrompt<T>), PromptValidator<T> validator = null, string defaultLocale = null)
|
||||
: base(dialogId, validator)
|
||||
: base(dialogId ?? nameof(NumberPrompt<T>), validator)
|
||||
{
|
||||
DefaultLocale = defaultLocale;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Microsoft.Bot.Builder.Dialogs
|
|||
public class TextPrompt : Prompt<string>
|
||||
{
|
||||
public TextPrompt(string dialogId = nameof(TextPrompt), PromptValidator<string> validator = null)
|
||||
: base(dialogId, validator)
|
||||
: base(dialogId ?? nameof(TextPrompt), validator)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Dialogs.Composition.Expressions;
|
||||
using Microsoft.Bot.Builder.Dialogs.Flow;
|
||||
using Microsoft.Bot.Builder.Dialogs.Flow.Loader;
|
||||
using Microsoft.Bot.Builder.Dialogs.Flow.Loader.Converters;
|
||||
using Microsoft.Bot.Builder.Dialogs.Flow.Loader.Contract;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Dialogs.Loader.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class JsonLoadTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task JsonDialogLoad_ChainedPromptsAndSelfLoop()
|
||||
{
|
||||
string json = File.ReadAllText("TestFlows/ChainedPromptsAndSwitch.json");
|
||||
|
||||
var dialog = DialogLoader.Load(json);
|
||||
|
||||
var convoState = new ConversationState(new MemoryStorage());
|
||||
var dialogState = convoState.CreateProperty<DialogState>("dialogState");
|
||||
|
||||
var adapter = new TestAdapter()
|
||||
.Use(new TranscriptLoggerMiddleware(new TraceTranscriptLogger()))
|
||||
.Use(new AutoSaveStateMiddleware(convoState));
|
||||
|
||||
var dialogs = new DialogSet(dialogState);
|
||||
|
||||
dialogs.Add(dialog);
|
||||
|
||||
await new TestFlow(adapter, async (turnContext, cancellationToken) =>
|
||||
{
|
||||
var state = await dialogState.GetAsync(turnContext, () => new DialogState());
|
||||
|
||||
var dialogContext = await dialogs.CreateContextAsync(turnContext, cancellationToken);
|
||||
|
||||
var results = await dialogContext.ContinueDialogAsync(cancellationToken);
|
||||
if (results.Status == DialogTurnStatus.Empty)
|
||||
results = await dialogContext.BeginDialogAsync(dialog.Id, null, cancellationToken);
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("What is your name?")
|
||||
.Send("x")
|
||||
.AssertReply("What is your name?")
|
||||
.Send("Joe")
|
||||
.AssertReply("What is your age?")
|
||||
.Send("64")
|
||||
.AssertReply("Done")
|
||||
.StartTestAsync();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="1.3.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="1.3.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Dialogs.Composition\Microsoft.Bot.Builder.Dialogs.Composition.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Dialogs.Flow.Loader\Microsoft.Bot.Builder.Dialogs.Flow.Loader.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Dialogs.Flow\Microsoft.Bot.Builder.Dialogs.Flow.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="TestFlows\ChainedPromptsAndSwitch.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,81 @@
|
|||
{
|
||||
"initialNodeId": "NameFlowNode",
|
||||
"Dialogs": [
|
||||
{
|
||||
"Id": "NameFlowNode",
|
||||
"Dialog": {
|
||||
"$type": "http://schemas.botframework.com/TextPrompt",
|
||||
"Id": "NamePrompt",
|
||||
"DefaultOptions": {
|
||||
"Prompt": {
|
||||
"type": "message",
|
||||
"text": "What is your name?"
|
||||
},
|
||||
"RetryPrompt": {
|
||||
"type": "message",
|
||||
"text": "Reprompt: What is your name?"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Commands": [
|
||||
{
|
||||
"$type": "http://schemas.botframework.com/SetVariable",
|
||||
"Name": "Name",
|
||||
"Value": "DialogTurnResult.Result"
|
||||
},
|
||||
{
|
||||
"$type": "http://schemas.botframework.com/Switch",
|
||||
"IgnoreCase": false,
|
||||
"Condition": "Name.Length > 2",
|
||||
"Cases": {
|
||||
"true": {
|
||||
"$type": "http://schemas.botframework.com/CallDialog",
|
||||
"DialogId": "NumberFlowNode"
|
||||
},
|
||||
"false": {
|
||||
"$type": "http://schemas.botframework.com/CallDialog",
|
||||
"DialogId": "NameFlowNode"
|
||||
}
|
||||
},
|
||||
"DefaultAction": {
|
||||
"$type": "http://schemas.botframework.com/SendActivity",
|
||||
"Text": "default"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "NumberFlowNode",
|
||||
"Dialog": {
|
||||
"$type": "http://schemas.botframework.com/IntNumberPrompt",
|
||||
"Id": "NumberPrompt",
|
||||
"DefaultOptions": {
|
||||
"Prompt": {
|
||||
"type": "message",
|
||||
"text": "What is your age?"
|
||||
},
|
||||
"RetryPrompt": {
|
||||
"type": "message",
|
||||
"text": "Reprompt: What is your age?"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Commands": [
|
||||
{
|
||||
"$type": "http://schemas.botframework.com/SetVariable",
|
||||
"Name": "Age",
|
||||
"Value": "DialogTurnResult.Result"
|
||||
},
|
||||
{
|
||||
"$type": "http://schemas.botframework.com/SetVariable",
|
||||
"Name": "IsChild",
|
||||
"Value": "Age < 18"
|
||||
},
|
||||
{
|
||||
"$type": "http://schemas.botframework.com/SendActivity",
|
||||
"Text": "Done"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
|
Загрузка…
Ссылка в новой задаче