Resolver.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 Autofac;
36 using Microsoft.Bot.Connector;
37 using System;
38 using System.Collections.Generic;
39 using System.Linq;
40 using System.Text;
41 using System.Threading.Tasks;
42 
43 namespace Microsoft.Bot.Builder.Internals.Scorables
44 {
51  public interface IResolver
52  {
53  bool TryResolve(Type type, object tag, out object value);
54  }
55 
56  public delegate bool TryResolve(Type type, object tag, out object value);
57 
58  public static partial class Extensions
59  {
60  public static bool TryResolve<T>(this IResolver resolver, object tag, out T value)
61  {
62  object inner;
63  if (resolver.TryResolve(typeof(T), tag, out inner))
64  {
65  value = (T)inner;
66  return true;
67  }
68  else
69  {
70  value = default(T);
71  return false;
72  }
73  }
74  }
75 
76  public sealed class NullResolver : IResolver
77  {
78  public static readonly IResolver Instance = new NullResolver();
79  private NullResolver()
80  {
81  }
82  bool IResolver.TryResolve(Type type, object tag, out object value)
83  {
84  value = null;
85  return false;
86  }
87  }
88 
89  public abstract class DelegatingResolver : IResolver
90  {
91  protected readonly IResolver inner;
92  protected DelegatingResolver(IResolver inner)
93  {
94  SetField.NotNull(out this.inner, nameof(inner), inner);
95  }
96  public virtual bool TryResolve(Type type, object tag, out object value)
97  {
98  return inner.TryResolve(type, tag, out value);
99  }
100  }
101 
102  public sealed class ArrayResolver : DelegatingResolver
103  {
104  private readonly object[] services;
105  public ArrayResolver(IResolver inner, params object[] services)
106  : base(inner)
107  {
108  SetField.NotNull(out this.services, nameof(services), services);
109  }
110 
111  public override bool TryResolve(Type type, object tag, out object value)
112  {
113  if (tag == null)
114  {
115  for (int index = 0; index < this.services.Length; ++index)
116  {
117  var service = this.services[index];
118  if (service != null)
119  {
120  var serviceType = service.GetType();
121  if (type.IsAssignableFrom(serviceType))
122  {
123  value = service;
124  return true;
125  }
126  }
127  }
128  }
129 
130  return base.TryResolve(type, tag, out value);
131  }
132  }
133 
137  public sealed class ActivityResolver : DelegatingResolver
138  {
140  : base(inner)
141  {
142  }
143 
144  public static readonly IReadOnlyDictionary<string, Type> TypeByName = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase)
145  {
150  { ActivityTypes.Ping, typeof(IActivity) },
151  { ActivityTypes.Typing, typeof(ITypingActivity) },
152  };
153 
154  public override bool TryResolve(Type type, object tag, out object value)
155  {
156  if (tag == null)
157  {
158  // if type is Activity, we're not delegating to the inner IResolver.
159  if (typeof(IActivity).IsAssignableFrom(type))
160  {
161  // if we have a registered IActivity
162  IActivity activity;
163  if (this.inner.TryResolve<IActivity>(tag, out activity))
164  {
165  // then make sure the IActivity.Type allows the desired type
166  Type allowedType;
167  if (TypeByName.TryGetValue(activity.Type, out allowedType))
168  {
169  if (type.IsAssignableFrom(allowedType))
170  {
171  // and make sure the actual CLR type also allows the desired type
172  // (this is true most of the time since Activity implements all of the interfaces)
173  Type clrType = activity.GetType();
174  if (allowedType.IsAssignableFrom(clrType))
175  {
176  value = activity;
177  return true;
178  }
179  }
180  }
181  }
182 
183  // otherwise we were asking for IActivity and it wasn't assignable from the IActivity.Type
184  value = null;
185  return false;
186  }
187  }
188 
189  // delegate to the inner for all remaining type resolutions
190  return base.TryResolve(type, tag, out value);
191  }
192  }
193 
194  public sealed class AutofacResolver : DelegatingResolver
195  {
196  private readonly ILifetimeScope scope;
197  public AutofacResolver(ILifetimeScope scope, IResolver inner)
198  : base(inner)
199  {
200  SetField.NotNull(out this.scope, nameof(scope), scope);
201  }
202 
203  public override bool TryResolve(Type type, object tag, out object value)
204  {
205  if (tag != null && this.scope.TryResolveKeyed(tag, type, out value))
206  {
207  return true;
208  }
209  else if (this.scope.TryResolve(type, out value))
210  {
211  return true;
212  }
213 
214  return base.TryResolve(type, tag, out value);
215  }
216  }
217 }
AutofacResolver(ILifetimeScope scope, IResolver inner)
Definition: Resolver.cs:197
Root namespace for the Microsoft Bot Connector SDK.
Definition: ActionTypes.cs:7
const string ContactRelationUpdate
Bot added removed to contact list
const string Message
Message from a user -> bot or bot -> User
virtual bool TryResolve(Type type, object tag, out object value)
Definition: Resolver.cs:96
ArrayResolver(IResolver inner, params object[] services)
Definition: Resolver.cs:105
Namespace for internal machinery that is not useful for most developers.
const string Ping
Bounce a message off of the server without replying or changing it&#39;s state
delegate bool TryResolve(Type type, object tag, out object value)
The Properties of a conversation are different
override bool TryResolve(Type type, object tag, out object value)
Definition: Resolver.cs:111
const string DeleteUserData
Delete user data
bool TryResolve(Type type, object tag, out object value)
basic shared properties for all activities
Definition: IActivity.cs:9
override bool TryResolve(Type type, object tag, out object value)
Definition: Resolver.cs:203
const string Typing
a user is typing
Someone has added a message to the conversation
override bool TryResolve(Type type, object tag, out object value)
Definition: Resolver.cs:154
const string ConversationUpdate
This notification is sent when the conversation&#39;s properties change, for example the topic name...
Allow the resolution of values based on type and optionally tag.
Definition: Resolver.cs:51
A resolver to recover C# type information from Activity schema types.
Definition: Resolver.cs:137
Namespace for the internal fibers machinery that is not useful for most developers.
Definition: Awaitable.cs:36
Root namespace for the Microsoft Bot Builder SDK.