Bot Framework V4 инъекция зависимости не работает - PullRequest
4 голосов
/ 07 марта 2020

Я использую. Net Core 2.1 для сборки бота с версией 4, как в примере здесь , и я не получаю никакого ответа от эмулятора Bot Framework или ошибки кода из Visual Studio. Когда я go из URL, это говорит об этой ошибке на изображении ниже. Я думаю, что-то не так с внедрением зависимости. Что я делаю не так?

enter image description here

При запуске:

public class Startup
    {
        public Startup(IConfiguration configuration, IHostingEnvironment env)
        {
            Configuration = configuration;
            var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
            configuration = builder.Build();

        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            // Create the Bot Framework Adapter with error handling enabled.
            services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();

            // Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
           // services.AddTransient<IBot, MyBot>();

            // Create the credential provider to be used with the Bot Framework Adapter.
            services.AddSingleton<ICredentialProvider, ConfigurationCredentialProvider>();

            // Create the Bot Framework Adapter.

            // storage
            services.AddSingleton<IStorage, MemoryStorage>();

            // Create the User state. (Used in this bot's Dialog implementation.)
            services.AddSingleton<UserState>();

            services.AddSingleton<RootDialog>();
            services.AddTransient<IBot, DialogBot<RootDialog>>();

            // Create the Conversation state. (Used by the Dialog system itself.)
            services.AddSingleton<ConversationState>();

            services.AddSingleton(Configuration);

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            app.UseDefaultFiles();
            app.UseStaticFiles();
            app.UseWebSockets();
            app.UseMvc();
            app.UseBotFramework();

        }
    }

В DialogBot.cs:

 public class DialogBot<T>: ActivityHandler where T : Dialog
    {
        protected readonly BotState ConversationState;
        protected readonly Dialog Dialog;
        protected readonly ILogger Logger;
        protected readonly BotState UserState;

        public DialogBot(ConversationState conversationState, UserState userState, T dialog, ILogger<DialogBot<T>> logger)
        {
            ConversationState = conversationState;
            UserState = userState;
            Dialog = dialog;
            Logger = logger;
        }

        public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            await base.OnTurnAsync(turnContext, cancellationToken);

            // Save any state changes that might have occured during the turn.
            await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
            await UserState.SaveChangesAsync(turnContext, false, cancellationToken);
        }

        protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            Logger.LogInformation("Running dialog with Message Activity.");

            // Run the Dialog with the new message Activity.
            await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
        }
        protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
        {
            foreach (var member in membersAdded)
            {
                if (member.Id != turnContext.Activity.Recipient.Id)
                {
                    await turnContext.SendActivityAsync(MessageFactory.Text($"Welcome!"), cancellationToken);
                }
            }
        }

In RootDialog.cs:

[Serializable]
    public class RootDialog : ComponentDialog
    {
        protected readonly ILogger _logger;
        protected readonly Dialog _dialog;
        protected readonly BotState _conversationState;
        protected readonly AdapterWithErrorHandler _adapterWithErrorHandler;
        protected readonly Encryption _encryption;
        private readonly IConfiguration _iConfiguration;


        public RootDialog(ConversationState conversationState, Dialog dialog,ILogger<RootDialog> Logger, AdapterWithErrorHandler AdapterWithErrorHandler, Encryption Encryption, IConfiguration configuration)
        {
            _conversationState = conversationState;
            _dialog = dialog;
            _logger = Logger;
            _adapterWithErrorHandler = AdapterWithErrorHandler;
            _encryption = Encryption;
            _iConfiguration = configuration;
        }

        const string HeroCard = "Hero Card";
        const string ThumbnailCard = "Thumbnail Card";

        private async Task<DialogTurnResult> StartDialogAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            // Start the child dialog. This will run the top slot dialog than will complete when all the properties are gathered.
            return await stepContext.BeginDialogAsync("slot-dialog", null, cancellationToken);
        }
}

Эмулятор:

enter image description here

1 Ответ

1 голос
/ 07 марта 2020

Удалить

Dialog dialog,

из вашего RootDialog.

Это не имеет смысла, и контейнер не знает, как разрешить его для инъекции в целевой класс.

RootDialog, таким образом, будет рефакторинг к

[Serializable]
public class RootDialog : ComponentDialog {
    protected readonly ILogger _logger;        
    protected readonly BotState _conversationState;
    protected readonly AdapterWithErrorHandler _adapterWithErrorHandler;
    protected readonly Encryption _encryption;
    private readonly IConfiguration _iConfiguration;

    public RootDialog(ConversationState conversationState, ILogger<RootDialog> logger, AdapterWithErrorHandler adapterWithErrorHandler, Encryption encryption, IConfiguration configuration) {
        _conversationState = conversationState;            
        _logger = logger;
        _adapterWithErrorHandler = adapterWithErrorHandler;
        _encryption = encryption;
        _iConfiguration = configuration;
    }

    const string HeroCard = "Hero Card";
    const string ThumbnailCard = "Thumbnail Card";

    private async Task<DialogTurnResult> StartDialogAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        // Start the child dialog. This will run the top slot dialog than will complete when all the properties are gathered.
        return await stepContext.BeginDialogAsync("slot-dialog", null, cancellationToken);
    }
}

Убедитесь, что что все явные зависимости, которые должны быть внедрены в целевой класс, зарегистрированы в коллекции служб и, соответственно, в контейнере DI.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...