AzureModule.cs
1 //
2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license.
4 //
5 // Microsoft Bot Framework: http://botframework.com
6 //
7 // Bot Builder SDK Github:
8 // https://github.com/Microsoft/BotBuilder
9 //
10 // Copyright (c) Microsoft Corporation
11 // All rights reserved.
12 //
13 // MIT License:
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 //
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 //
25 // THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33 
34 using System;
35 using System.Collections.Generic;
36 using System.Linq;
37 using System.Reflection;
38 using System.Runtime.Serialization;
39 using System.Runtime.Serialization.Formatters;
40 using System.Runtime.Serialization.Formatters.Binary;
41 using Autofac;
44 using Microsoft.Bot.Connector;
45 using Module = Autofac.Module;
46 
47 namespace Microsoft.Bot.Builder.Azure
48 {
52  public sealed class AzureModule : Module
53  {
54 
58  public static readonly object Key_DataStore = new object();
59 
60  private readonly Assembly assembly;
61 
69  public AzureModule(Assembly assembly)
70  {
71  SetField.NotNull(out this.assembly, nameof(assembly), assembly);
72  }
73 
78  protected override void Load(ContainerBuilder builder)
79  {
80  builder.RegisterType<ConnectorStore>()
81  .AsSelf()
82  .InstancePerLifetimeScope();
83 
84  // if application settings indicate that bot should use the table storage,
85  // TableBotDataStore will be registered as underlying storage
86  // otherwise bot connector state service will be used.
87  if (ShouldUseTableStorage())
88  {
89  builder.Register(c => MakeTableBotDataStore())
90  .Keyed<IBotDataStore<BotData>>(Key_DataStore)
91  .AsSelf()
92  .SingleInstance();
93  }
94  else
95  {
96  builder.Register(c => new ConnectorStore(c.Resolve<IStateClient>()))
97  .Keyed<IBotDataStore<BotData>>(Key_DataStore)
98  .AsSelf()
99  .InstancePerLifetimeScope();
100  }
101 
102  // register the data store with caching data store
103  // and set the consistency policy to be "Last write wins".
104  builder.Register(c => new CachingBotDataStore(c.ResolveKeyed<IBotDataStore<BotData>>(Key_DataStore),
107  .AsSelf()
108  .InstancePerLifetimeScope();
109 
110  // register the appropriate StateClient based on the state api url.
111  builder.Register(c =>
112  {
113  var activity = c.Resolve<IActivity>();
114  if (activity.ChannelId == "emulator")
115  {
116  // for emulator we should use serviceUri of the emulator for storage
117  return new StateClient(new Uri(activity.ServiceUrl));
118  }
119 
120  MicrosoftAppCredentials.TrustServiceUrl(BotService.stateApi.Value, DateTime.MaxValue);
121  return new StateClient(new Uri(BotService.stateApi.Value));
122  })
123  .As<IStateClient>()
124  .InstancePerLifetimeScope();
125 
126  // register the bot service serialization binder for type mapping to current assembly
127  builder.Register(c => new BotServiceSerializationBinder(assembly))
128  .AsSelf()
129  .As<SerializationBinder>()
130  .InstancePerLifetimeScope();
131 
132  // register the Delegate surrogate provide to map delegate to current assembly during deserialization
133  builder
134  .Register(c => new BotServiceDelegateSurrogate(assembly))
135  .AsSelf()
136  .InstancePerLifetimeScope();
137 
138  // extend surrogate providers with bot service delegate surrogate provider and register the surrogate selector
139  builder
140  .Register(c =>
141  {
142  var providers = c.ResolveKeyed<IEnumerable<Serialization.ISurrogateProvider>>(FiberModule.Key_SurrogateProvider).ToList();
143  // need to add the latest delegate surrogate to make sure that surrogate selector
144  // can deal with latest assembly
145  providers.Add(c.Resolve<BotServiceDelegateSurrogate>());
146  return new Serialization.SurrogateSelector(providers);
147  })
148  .As<ISurrogateSelector>()
149  .InstancePerLifetimeScope();
150 
151  // register binary formatter used for binary serialization operation
152  builder
153  .Register((c, p) => new BinaryFormatter(c.Resolve<ISurrogateSelector>(), new StreamingContext(StreamingContextStates.All, c.Resolve<Serialization.StoreInstanceByTypeSurrogate.IResolver>(p)))
154  {
155  AssemblyFormat = FormatterAssemblyStyle.Simple,
156  Binder = c.Resolve<SerializationBinder>()
157  })
158  .As<IFormatter>()
159  .InstancePerLifetimeScope();
160  }
161 
162  private bool ShouldUseTableStorage()
163  {
164  bool shouldUseTableStorage = false;
166  return bool.TryParse(useTableStore, out shouldUseTableStorage) && shouldUseTableStorage;
167  }
168 
169  private TableBotDataStore MakeTableBotDataStore()
170  {
172 
173  if (!string.IsNullOrEmpty(connectionString))
174  {
175  return new TableBotDataStore(connectionString);
176  }
177 
178  // no connection string in application settings but should use table storage flag is set.
179  throw new ArgumentException("connection string for table storage is not set in application setting.");
180  }
181  }
182 }
The Bot State REST API allows your bot to store and retrieve state associated with conversations cond...
Definition: IStateClient.cs:50
Autofac module for Fiber components.
Definition: FiberModule.cs:50
A utility class for bots running on Azure.
Root namespace for the Microsoft Bot Connector SDK.
Definition: ActionTypes.cs:7
Extend ISerializationSurrogate with a "tester" method used by SurrogateSelector.
IBotDataStore<T> Implementation using Azure Storage Table
Caches data for BotDataBase<T> and wraps the data in BotData to be stored in CachingBotDataStore.inner
AzureModule(Assembly assembly)
Instantiates the azure module.
Definition: AzureModule.cs:69
CachingBotDataStoreConsistencyPolicy
The data consistency policy for CachingBotDataStore
static string GetAppSetting(string key)
Get value corresponding to the key from application settings.
Namespace for internal machinery that is not useful for most developers.
The Bot State REST API allows your bot to store and retrieve state associated with conversations cond...
Definition: StateClient.cs:57
This surrogate is responsible for serialization of delegates and map them to the matching delegates i...
Namespace for internal Dialogs machinery that is not useful for most developers.
basic shared properties for all activities
Definition: IActivity.cs:9
const string UseTableStorageForConversationState
Key for the flag indicating if table storage should be used as bot state store.
override void Load(ContainerBuilder builder)
Registers dependencies with the builder .
Definition: AzureModule.cs:78
SerializationBinder responsible for mapping the matching types to the types in the assembly passed to...
Namespace for the internal fibers machinery that is not useful for most developers.
Definition: Awaitable.cs:36
Core namespace for Dialogs and associated infrastructure.
Definition: Address.cs:40
implementation of IBotDatStore which uses the State REST API on state.botframework.com to store data
Root namespace for the Microsoft Bot Builder SDK.
const string TableStorageConnectionString
The key for azure table storage connection string.
Autofac module for azure bot components.
Definition: AzureModule.cs:52