Reputation: 379
I've been playing around with the bot framework, but I was just wondering if my usage of Autofac is correct when using using context.Call(). Should I be passing the rating service depency from the RootDialog to the ReviewDialog like this(below), or is there a better way?
context.Call(new ReviewDialog(_ratingService), ChildDialogHasCompleted);
MessagesController
[BotAuthentication]
public class MessagesController : ApiController
{
/// <summary>
/// POST: api/Messages
/// Receive a message from a user and reply to it
/// </summary>
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
await Conversation.SendAsync(activity, () => scope.Resolve<IDialog<object>>());
}
}
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
}
RootDialog
[Serializable]
public class RootDialog : LuisDialog<object>
{
private IRatingService _ratingService;
public RootDialog(IRatingService ratingService)
{
this._ratingService = ratingService;
}
[LuisIntent("Movie")]
public async Task IntentSearch(IDialogContext context, LuisResult result)
{
// Do stuff
context.Call(new ReviewDialog(_ratingService), ChildDialogHasCompleted);
}
private async Task ChildDialogHasCompleted(IDialogContext context, IAwaitable<object> msg)
{
context.Done(true);
}
}
ReviewDialog
[Serializable]
public class ReviewDialog : IDialog
{
private IRatingService _ratingService;
public ReviewDialog(IRatingService ratingService)
{
this._ratingService = ratingService;
}
public async Task StartAsync(IDialogContext context)
{
PromptDialog.Choice(context, ProcessRating, new List<string> { "1", "2", "3", "4", "5" }, "Please select your rating");
}
public async Task ProcessRating(IDialogContext context, IAwaitable<string> msg)
{
var message = await msg;
context.UserData.TryGetValue("SelectedMovieId", out int movieId);
var rating = int.Parse(message);
_ratingService.Save(movieId, rating);
await context.PostAsync("Thank you");
context.Done(true);
}
}
Global
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
var builder = new ContainerBuilder();
builder.RegisterType<RootDialog>()
.As<IDialog<object>>()
.InstancePerDependency();
builder.RegisterType<RatingService>()
.Keyed<IRatingService>(FiberModule.Key_DoNotSerialize)
.AsImplementedInterfaces();
builder.Update(Conversation.Container);
}
}
Any help would be greatly appreciated.
Upvotes: 2
Views: 372
Reputation: 3426
The way you are doing this is totally valid. To see another implementaiton please check out AlarmBot
The way you are doing this is generally how I use DI in dialogs as well. there is another way to pass data/classes between dialogs using the data bags inside the context PrivateConversationData
, ConversationData
and UserData
, but there is nothing wrong with the way you are doing it
Upvotes: 1