ScorableBase.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 
36 using System;
37 using System.Collections.Generic;
38 using System.Diagnostics;
39 using System.Linq;
40 using System.Reflection;
41 using System.Threading;
42 using System.Threading.Tasks;
43 
44 namespace Microsoft.Bot.Builder.Scorables.Internals
45 {
54  [Serializable]
55  public abstract class ScorableBase<Item, State, Score> : IScorable<Item, Score>
56  {
57  protected abstract Task<State> PrepareAsync(Item item, CancellationToken token);
58 
59  protected abstract bool HasScore(Item item, State state);
60 
61  protected abstract Score GetScore(Item item, State state);
62 
63  protected abstract Task PostAsync(Item item, State state, CancellationToken token);
64 
65  protected abstract Task DoneAsync(Item item, State state, CancellationToken token);
66 
67  [DebuggerStepThrough]
68  async Task<object> IScorable<Item, Score>.PrepareAsync(Item item, CancellationToken token)
69  {
70  return await this.PrepareAsync(item, token);
71  }
72 
73  [DebuggerStepThrough]
74  bool IScorable<Item, Score>.HasScore(Item item, object opaque)
75  {
76  var state = (State)opaque;
77  return this.HasScore(item, state);
78  }
79 
80  [DebuggerStepThrough]
81  Score IScorable<Item, Score>.GetScore(Item item, object opaque)
82  {
83  var state = (State)opaque;
84  if (!HasScore(item, state))
85  {
86  throw new InvalidOperationException();
87  }
88 
89  return this.GetScore(item, state);
90  }
91 
92  [DebuggerStepThrough]
93  Task IScorable<Item, Score>.PostAsync(Item item, object opaque, CancellationToken token)
94  {
95  try
96  {
97  var state = (State)opaque;
98  if (!HasScore(item, state))
99  {
100  throw new InvalidOperationException();
101  }
102 
103  return this.PostAsync(item, state, token);
104  }
105  catch (OperationCanceledException error)
106  {
107  return Task.FromCanceled(error.CancellationToken);
108  }
109  catch (Exception error)
110  {
111  return Task.FromException(error);
112  }
113  }
114 
115  [DebuggerStepThrough]
116  Task IScorable<Item, Score>.DoneAsync(Item item, object opaque, CancellationToken token)
117  {
118  try
119  {
120  var state = (State)opaque;
121 
122  return this.DoneAsync(item, state, token);
123  }
124  catch (OperationCanceledException error)
125  {
126  return Task.FromCanceled(error.CancellationToken);
127  }
128  catch (Exception error)
129  {
130  return Task.FromException(error);
131  }
132  }
133  }
134 
135 
136  [Serializable]
137  public abstract class DelegatingScorable<Item, Score> : IScorable<Item, Score>
138  {
139  protected readonly IScorable<Item, Score> inner;
140 
142  {
143  SetField.NotNull(out this.inner, nameof(inner), inner);
144  }
145 
146  public override string ToString()
147  {
148  return this.inner.ToString();
149  }
150 
151  public virtual Task<object> PrepareAsync(Item item, CancellationToken token)
152  {
153  try
154  {
155  return this.inner.PrepareAsync(item, token);
156  }
157  catch (OperationCanceledException error)
158  {
159  return Task.FromCanceled<object>(error.CancellationToken);
160  }
161  catch (Exception error)
162  {
163  return Task.FromException<object>(error);
164  }
165  }
166 
167  public virtual bool HasScore(Item item, object state)
168  {
169  return this.inner.HasScore(item, state);
170  }
171 
172  public virtual Score GetScore(Item item, object state)
173  {
174  return this.inner.GetScore(item, state);
175  }
176 
177  public virtual Task PostAsync(Item item, object state, CancellationToken token)
178  {
179  try
180  {
181  return this.inner.PostAsync(item, state, token);
182  }
183  catch (OperationCanceledException error)
184  {
185  return Task.FromCanceled(error.CancellationToken);
186  }
187  catch (Exception error)
188  {
189  return Task.FromException(error);
190  }
191  }
192 
193  public virtual Task DoneAsync(Item item, object state, CancellationToken token)
194  {
195  try
196  {
197  return this.inner.DoneAsync(item, state, token);
198  }
199  catch (OperationCanceledException error)
200  {
201  return Task.FromCanceled(error.CancellationToken);
202  }
203  catch (Exception error)
204  {
205  return Task.FromException(error);
206  }
207  }
208  }
209 
213  public class Token<InnerItem, InnerScore>
214  {
215  public InnerItem Item;
217  public object State;
218  }
219 
223  [Serializable]
224  public abstract class ScorableAggregator<OuterItem, OuterState, OuterScore, InnerItem, InnerState, InnerScore> : ScorableBase<OuterItem, OuterState, OuterScore>
225  where OuterState : Token<InnerItem, InnerScore>
226  {
227  protected override bool HasScore(OuterItem item, OuterState state)
228  {
229  if (state != null)
230  {
231  return state.Scorable.HasScore(state.Item, state.State);
232  }
233 
234  return false;
235  }
236 
237  protected override Task PostAsync(OuterItem item, OuterState state, CancellationToken token)
238  {
239  try
240  {
241  return state.Scorable.PostAsync(state.Item, state.State, token);
242  }
243  catch (OperationCanceledException error)
244  {
245  return Task.FromCanceled(error.CancellationToken);
246  }
247  catch (Exception error)
248  {
249  return Task.FromException(error);
250  }
251  }
252 
253  protected override Task DoneAsync(OuterItem item, OuterState state, CancellationToken token)
254  {
255  try
256  {
257  if (state != null)
258  {
259  return state.Scorable.DoneAsync(state.Item, state.State, token);
260  }
261  else
262  {
263  return Task.CompletedTask;
264  }
265  }
266  catch (OperationCanceledException error)
267  {
268  return Task.FromCanceled(error.CancellationToken);
269  }
270  catch (Exception error)
271  {
272  return Task.FromException(error);
273  }
274  }
275  }
276 }
Score GetScore(Item item, object state)
Gets the score for this item.
virtual Task< object > PrepareAsync(Item item, CancellationToken token)
override bool HasScore(OuterItem item, OuterState state)
Task< object > PrepareAsync(Item item, CancellationToken token)
Perform some asynchronous work to analyze the item and produce some opaque state. ...
Task DoneAsync(Item item, object state, CancellationToken token)
The scoring process has completed - dispose of any scoped resources.
virtual Task DoneAsync(Item item, object state, CancellationToken token)
Allow the scoring of items, with external comparison of scores, and enable the winner to take some ac...
Definition: Scorable.cs:49
override Task DoneAsync(OuterItem item, OuterState state, CancellationToken token)
Aggregates some non-empty set of inner scorables to produce an outer scorable.
Allow for static type checking of opaque state for convenience of scorable implementations.
Definition: ScorableBase.cs:55
Task PostAsync(Item item, object state, CancellationToken token)
If this scorable wins, this method is called.
Namespace for scorable interfaces, classes and compositions.
Namespace for internal machinery that is not useful for most developers and may change in the future...
virtual Task PostAsync(Item item, object state, CancellationToken token)
override Task PostAsync(OuterItem item, OuterState state, CancellationToken token)
virtual Score GetScore(Item item, object state)
Provides the state to aggregate the state (and associated scorable) of multiple scorables.
bool HasScore(Item item, object state)
Returns whether this scorable wants to participate in scoring this item.
IScorable< InnerItem, InnerScore > Scorable
Namespace for the internal fibers machinery that is not useful for most developers and may change in ...
Root namespace for the Microsoft Bot Builder SDK.